1. 创建多线程
在Java中,实现线程的方式大体上分为三种,通过继承Thread类、实现Runnable接口,实现Callable接口。简单的示例代码分别如下所示。
1.1 创建多线程的3种方式
在了解此3种方式之前,我可以告诉你们任何方式都绕不开Thread类。
1.1.1 继承Thread类
// **测试类:**
public class MyThread extends Thread {
public void run(){
for(int i = 0; i < 5; i++){
System.out.println(Thread.currentThread() + ":" + i);
}
}
public static void main(String[] args) {
MyThread myThread1 = new MyThread();
MyThread myThread2 = new MyThread();
MyThread myThread3 = new MyThread();
myThread1.start();
myThread2.start();
myThread3.start();
}
}
// Thread类
public
class Thread implements Runnable {
public synchronized void start() {
if (threadStatus != 0)
throw new IllegalThreadStateException();
group.add(this);
boolean started = false;
try {
start0(); // 调用start0(),系统创建新线程
started = true;
} finally {
try {
if (!started) {
group.threadStartFailed(this);
}
} catch (Throwable ignore) {
/* do nothing. If start0 threw a Throwable then
it will be passed up the call stack */
}
}
}
// 注意,这里并不是没有实现方法,native关键字表示此方法在c/c++中实现,java源码中没有
private native void start0();
}
疑问:
- 为什么继承Thread必须要重写run方法
- 为什么Thread类中start()并没有调用run(),而实际上却调用了呢?
1.1.2 实现Runnable接口
public class MyThread implements Runnable{
public static int count = 20;
@Override
public void run() {
while(count > 0){
try {
Thread.sleep(200);
}catch (InterruptedException e){
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+"-当前剩余票数:"+count--);
}
}
public static void main(String[] args) {
MyThread Thread1=new MyThread();
// 实际上还是将实现Runnable的实现类传入Thread初始化,与继承Thread类并重写run方法一样
Thread mThread1=new Thread(Thread1,"线程1");
Thread mThread2=new Thread(Thread1,"线程2");
Thread mThread3=new Thread(Thread1,"线程3");
mThread1.start();
mThread2.start();
mThread3.start();
}
}
1.1.3 实现Callable接口
此方式基于FutureTask类和Callable接口,通过实现Callable接口重写run方法,然后生成FutureTask对象,由于FutureTask继承了Runnable接口,所以通过传入FutureTask对象来初始化Thread类,从而实现线程创建。
// 重写Callable接口
public class MyThread implements Callable<String>{
private int count = 20;
@Override
public String call() throws Exception {
for (int i = count; i > 0; i--) {
// Thread.yield();
System.out.println(Thread.currentThread().getName()+"当前票数:" + i);
}
return "sale out";
}
public static void main(String[] args) throws InterruptedException, ExecutionException {
Callable<String> callable =new MyThread();
FutureTask<String> futureTask=new FutureTask<>(callable);
Thread mThread=new Thread(futureTask);
Thread mThread2=new Thread(futureTask);
Thread mThread3=new Thread(futureTask);
// mThread.setName("hhh");
mThread.start();
mThread2.start();
mThread3.start();
System.out.println(futureTask.get());
}
}