文章目录
继承java.lang.Thread(JDK1.0)类,覆写run()方法
无论哪种方式实现多线程,线程启动 一律按照Thread类提供的start()方法
start()才会让多个线程交替执行,run()只会让每个线程都执行自己的
start()方法详解
1.进方法之后判断线程状态,为0表示没启动,否则抛出IllegalThreadStateException(RunTimeException)。所以一个线程只能启动一次
2.调用本地方法start0()来将线程真正启动。(通过start0()调run())
3.JVM为线程准备好资源后,回调run()方法来执行具体任务
- 缺点:单继承局限
//继承Thread来实现多线程
class MyThread2 extends Thread {
private int ticket = 20;
private String title;
public MyThread2(String title) {
this.title = title;
}
public void run() {
while (ticket > 0) {
System.out.println("当前线程为"+title+"剩余票数为"+ticket--);
}
}
}
public class TestThread {
//1.实现Runnable来实现多线程
//2.继承Thread来实现多线程
public static void main(String[] args) {
MyThread2 myThread2 = new MyThread2("myThread2"); //1.创建真实线程类
MyThread2 myThread22 = new MyThread2("myThread2"); //1.创建真实线程类
MyThread2 myThread23 = new MyThread2("myThread23"); //1.创建真实线程类
//Thread类提供的构造可接收Runnable的对象
Thread thread1 = new Thread(myThread2); //2.三个代理线程类共享一个线程 20张票
Thread thread2 = new Thread(myThread22);
Thread thread3 = new Thread(myThread23);
thread1.start(); //3.启动线程
thread2.start();
thread3.start();
thread3.start();
}
}
实现Runnable接口,覆写run()方法
解决了单继承缺陷,利用Thread类的构造方法 public Thread(Runnable target) 传入Runnable对象调用start()方法
- 代理设计模式:
Thread
类和实现了Runnable
接口的自定义类
。
其中Thread
类实现辅助操作,包括线程里资源调度等任务,自定义线程类
完成真实业务
//实现Runnable来实现多线程
class MyThread implements Runnable {
private int ticket = 20;
public void run() {
while (ticket > 0) {
System.out.println("当前线程为"+Thread.currentThread().getName()+"剩余票数为"+ticket--);
}
}
}
public class TestRunnable {
public static void main(String[] args) {
MyThread myThread = new MyThread(); //1.创建真实线程类
Thread thread1 = new Thread(myThread,"买票人A"); //2.三个代理线程类共享一个线程 20张票
Thread thread2 = new Thread(myThread,"买票人B");
Thread thread3 = new Thread(myThread,"买票人C");
thread1.start(); //3.启动线程
thread2.start();
thread3.start();
}
}
继承Thread与实现Runnable的区别
1.Thread类有单继承缺陷,Runnable更加灵活;且Thread类也实现了Runnable接口,覆写其run()方法
2.实现Runnable接口可以更好的(相比而言更容易)实现程序共享的概念
比如卖票
假设创建两个Thread对象卖票 (new Thread().start),他俩会各卖个的;
但如果在这两个Thread对象new的过程中传入同一个Runnable子类对象(new Thread(runObj).start)。则会卖同一套票。
实现Callable接口,覆写call()方法
T call()方法有返回值,其返回值类型与Callable<T>接口的泛型类型一致
Callable接口和Thread没有直接联系,如何使用其start()方法呢?
Callable接口是Future的子接口。Future的get()方法可以拿到call方法的返回值
FutureTask类既实现了Future接口,又实现了Runnable接口。
FutureTask提供的构造方法允许传入Callable对象。
Thread类提供的构造方法允许传入Runnable对象->即可以将FutureTask子类传入,达到调用start()的目的。
- 类图
class MyThread3 implements Callable<String> {
private Integer ticket = 20;
@Override
public String call() throws Exception {
while (this.ticket > 0) {
System.out.println(Thread.currentThread().getName()+"当前剩余票数为"+this.ticket--);
}
return "票已售完,下次赶早~";
}
}
public class TestCallable {
public static void main(String[] args) throws ExecutionException, InterruptedException {
//1.有一个MyThread3对象
MyThread3 myThread3 = new MyThread3();
//2.有一个FutureTask对象接收callable 的返回值
FutureTask<String> futureTask =new FutureTask<>(myThread3);
//3.有一个Thread对象来启动线程,通过传入Future对象间接传入call()
Thread thread = new Thread(futureTask);
thread.start();
System.out.println(futureTask.get());
}
}