一、前言
Java语言的JVM允许程序运行多个线程,它通过java.lang.Thread 类来体现。
二、JDK1.5之前创建新执行线程有两种方法
继承Thread类的方式
实现Runnable接口的方式
三、继承Thread类的方式
1、使用继承Thread类的方式创建一个线程:
①.创建一个子类,继承于Thread线程类。
②.重写Thread类中的run()方法。-->将此线程执行的操作写在这里
③.创建一个子类的实例化对象。
④.使用此对象调用start()方法。
/*
输出100以内的偶数
*/
//1.创建一个子类,继承于Thread线程类。
class MyThread extends Thread{
//2.重写Thread类中的run()方法。
@Override
public void run() {
for (int i = 0; i < 100; i++) {
if (i % 2 == 0) {
System.out.println(Thread.currentThread().getName()+":" + i);
}
}
}
}
public class TreadTest {
public static void main(String[] args) {
//3.创建一个子类的实例化对象。
MyThread test1 = new MyThread();
//4.使用此对象调用start()方法。①启动当前线程 ②调用当前线程的run()方法。
test1.start();
//我们不能通过直接调用run()方法的方式开启线程
// test1.run();
//不能再次使用test调用start方法,否则会报异常:IllegalThreadStateException
// test1.start();
//我们需要建立新的线程的对象,再开启线程调start()方法
MyThread test2 = new MyThread();
test2.start();
//以下操作都是main线程进行执行
for (int i = 0; i < 100; i++) {
if (i % 2 == 0) {
System.out.println(Thread.currentThread().getName()+":" +i+"********main()************");
}
}
}
}
2、Thread类中的常用方法:
①.start():启动当前线程,并且调用run()。
②.run():通常需要重写此方法,将创建的线程要操作的代码写进此方法。
③.getName():获取线程名称
④.setNmae():设置线程名称
⑤.currentThread():静态方法,返回执行当前代码的线程。
⑥.yield():释放当前cpu的执行权,但其后也有可能继续被cpu进行执行处理当前线程。
⑦.join():在线程a中调用线程b的join()方法,此时线程a会进入阻塞状态,先将线程b全部执行结束线程a才会停止阻塞状态。
⑧.stop():已过时。表示结束当前线程。
⑨.sleep(long millitimes):让当前线程进入“睡眠”millitimes毫秒,在millitimes毫秒内,当前线程是阻塞状态。
⑩.isAlive():判断当前线程是否执行结束。
11.线程的优先级:
MIN_PRIORITY = 1;
MAX_PRIORITY=10;
NORM_PRIORITY = 5;
如何获取和设置线程的优先级?
获取当前线程的优先级:getPriority()
设置当前线程的优先级:setPriority(int p)
说明:高优先级的线程要抢占低优先级的线程CPU的执行权。但是这并不意味着高优先级的线程运行结束,低优先级的线程才能执行,只是从概率上讲。
class HelloThread extends Thread{
@Override
public void run() {
for (int i = 0; i < 100; i++) {
if(i % 2 == 0){
// try {
// sleep(10);
// } catch (InterruptedException e) {
// throw new RuntimeException(e);
// }
System.out.println(Thread.currentThread().getName() + ":" + getPriority() + ":" + i);
}
if(i % 20 == 0){
yield();
}
}
}
public HelloThread(String name) {
super(name);
}
}
public class ThreadMethodTest {
public static void main(String[] args) {
HelloThread h1 = new HelloThread("Thread:1");
// h1.setName("线程一");
h1.start();
h1.setPriority(Thread.MAX_PRIORITY);
//主线程操作
Thread.currentThread().setName("主线程");
Thread.currentThread().setPriority(Thread.MIN_PRIORITY);
for (int i = 0; i < 100; i++) {
if(i % 2 == 0){
System.out.println(Thread.currentThread().getName() + ":" +Thread.currentThread().getPriority() + ":" + i);
}
// if(i == 20){
// try {
// h1.join();
// } catch (InterruptedException e) {
// throw new RuntimeException(e);
// }
// }
}
// System.out.println(h1.isAlive());
}
}
四、实现了Runnable接口的方式
1、使用实现Runnable接口的实现类的方式创建一个线程:
①.创建一个实现了Runnable接口的实现类。 ②.重写Runnable接口中的抽象方法run()。 ③.实例化一个实现类的对象。并将这个实现类的对象当做参数传给Thread类的构造器形参。 ④.创建一个Thread的对象。 ⑤.Thread实例化对象调用start()。
//1.创建一个实现了Runnable接口的实现类。
class MThread implements Runnable{
//2.重写Runnable接口中的抽象方法run()。
@Override
public void run() {
for (int i = 0; i < 100; i++) {
if(i % 2 == 0){
System.out.println(Thread.currentThread().getName() + ":" + i);
}
}
}
}
public class ThreadTest1 {
public static void main(String[] args) {
//3.实例化一个实现类的对象。
MThread mThread = new MThread();
//4.创建一个Thread的对象。并将这个实现类的对象当做参数传给Thread类的构造器形参。
Thread thread1 = new Thread(mThread);
Thread thread2 = new Thread(mThread);
thread1.setName("线程1");
thread2.setName("线程2");
thread1.start();
thread2.start();
}
}
五、比较两种创建线程的方式
1、开发中,更多地使用实现Runnable接口的方式创建线程。
原因:①.实现接口的方式打破了Java的单继承的局限性。
②.实现Runnable接口的方式天然的处理了多个线程数据共享的问题。
2、两者的联系:观察Thread类源码我们发现,Thread类已实现了Runnable接口。
3、相同点:两者都要重写run(),将线程要处理的逻辑写进run()中。