java_多线程4种实现方式
1.继承Thread类
class MyThread extends Thread{ private int ticket = 5 ; public void run(){ for(int i=0;i<100;i++){ if(this.ticket>0){ System.out.println("卖票:ticket = " + ticket--) ; } } } }; public class ThreadDemo0{ public static void main(String args[]){ MyThread mt1 = new MyThread() ; MyThread mt2 = new MyThread() ; MyThread mt3 = new MyThread() ; mt1.run() ; //注意:调用的是run,并不是start
mt2.run() ;
mt3.run() ; } };
class Mythread extends Thread{ private int ticket = 5 ; public void run(){ for(int i=0;i<100;i++){ if(this.ticket>0){ System.out.println("卖票:ticket = " + ticket--) ; } } } }; public class ThreadDemo0{ public static void main(String args[]){ Mythread mt1 = new Mythread() ; Mythread mt2 = new Mythread() ; Mythread mt3 = new Mythread() ; mt1.start(); mt2.start(); mt3.start(); } };
注:start()用来启动一个线程,当调用start()方法时,系统才会开启一个线程,通过Thead类中start()方法来启动的线程处于就绪状态(可运行状态),
此时并没有运行,一旦得到CPU时间片,就自动开始执行run()方法。此时不需要等待run()方法执行完也可以继续执行下面的代码,
而run()方法是在本线程里的,只是线程里的一个函数,而不是多线程的。如果直接调用run(),其实就相当于是调用了一个普通函数而已,直接调用run()方法必须等待run()方法执行完毕才能执行下面的代码,所以执行路径还是只有一条,根本就没有线程的特征,所以在多线程执行时要使用start()方法而不是run()方法。
2.实现Runnable接口(无返回值得任务必须实现Runnable接口,可返回值的任务必须实现Callable接口)
public class Runnable_xc { public static void main(String[] args) { M1 m1 = new M1(); M2 m2 = new M2(); Thread t1 = new Thread(m1); Thread t2 = new Thread(m2); t1.start(); t2.start(); } } class M1 implements Runnable { public void run() { int i = 100; while (i > 0) { System.out.println(i--); } } } class M2 implements Runnable { public void run() { int i = 100; while (i > 0) { System.out.println(i--); } } }
以上两种方式在任务执行完成之后无法获取返回结果,如果就以上两种方法的话,推荐使用Runnable,简单的说就是因为单继承多实现
3.实现Callable接口通过FutureTask包装器来创建Thread线程(无返回值得任务必须实现Runnable接口,可返回值的任务必须实现Callable接口,重要的事情说2遍)
Callable接口(也只有一个方法)定义如下: 泛型接口,call()函数返回的类型就是传递进来的V类型,Callable经常和java线程池一起启用:
public interface Callable<V> { V call() throws Exception; }
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;
public class MyCallable implements Callable<String> {
public String call() throws Exception {
int i = 100;
String rs = "false";
while (i > 0) {
System.out.println(i--);
if (i == 50) {
Thread.sleep(3000);
}
if (i == 1) {
rs = "TRUE";
}
}
return rs;
}
public static void main(String[] args) {
Callable<String> oneCallable0 = new MyCallable(); // 由Callable<String>创建一个FutureTask<String>对象:
Callable<String> oneCallable1 = new MyCallable();
FutureTask<String> oneTask0 = new FutureTask<String>(oneCallable0);
FutureTask<String> oneTask1 = new FutureTask<String>(oneCallable1);
Thread oneThread0 = new Thread(oneTask0); // 由FutureTask<String>创建一个Thread对象:
Thread oneThread1 = new Thread(oneTask1);
oneThread0.start();
oneThread1.start();
try {
System.out.println(oneTask0.get());
System.out.println(oneTask1.get());//结果
} catch (InterruptedException | ExecutionException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
4.使用ExecutorService、Callable、Future
ExecutorService是一个线程池接口,执行Callable任务后,可以获取一个Future对象,在该对象上调用get就可以获取到Callable任务返回的Object,再结合ExecutorService接口就可以实现有返回结果的多线程
import java.util.ArrayList; import java.util.Date; import java.util.List; import java.util.concurrent.Callable; import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.Future; public class TH_POOL { public static void main(String[] args) throws ExecutionException, InterruptedException { System.out.println("----程序开始运行----"); Date date1 = new Date(); int taskSize = 5; // 创建一个线程池 ExecutorService pool = Executors.newFixedThreadPool(taskSize); // 创建多个有返回值的任务 List<Future> list = new ArrayList<Future>(); for (int i = 0; i < taskSize; i++) { Callable c = new MyCallable3(i + " "); // 执行任务并获取Future对象 Future f = pool.submit(c); list.add(f); } // 关闭线程池 pool.shutdown(); // 获取所有并发任务的运行结果 for (Future f : list) { // 从Future对象上获取任务的返回值,并输出到控制台 System.out.println(">>>" + f.get().toString()); } Date date2 = new Date(); System.out.println("----程序结束运行----,程序运行时间【" + (date2.getTime() - date1.getTime()) + "毫秒】"); } } class MyCallable3 implements Callable<Object> { private String taskNum; MyCallable3(String taskNum) { this.taskNum = taskNum; } public Object call() throws Exception { System.out.println(">>>" + taskNum + "任务启动"); Date dateTmp1 = new Date(); Thread.sleep(1000); Date dateTmp2 = new Date(); long time = dateTmp2.getTime() - dateTmp1.getTime(); System.out.println(">>>" + taskNum + "任务终止"); return taskNum + "任务返回运行结果,当前任务时间【" + time + "毫秒】"; } }
线程就先复习到这吧,手里还有点任务,表示并不想加班,所以没写那么细