多线程的创建
创建方式一:继承Thread类创建多线程
public class 多线程_1创建 { public static void main(String[] args) { //创建方式一 Thread t=new MyThread();//创建MyThread线程对象 //直接调run()方法会被当成普通方法执行,此时相当于还是单线程执行, // 所以需要调用start()方法启动多线程 t.start();//调用start()方法启动线程(实际执行的还是run()方法) //注意:子线程一定要放在主线程之前,不然先跑主线程还是会被当做是单线程 for (int i = 0; i < 6; i++) { System.out.println("主线程执行:"+i); } }}//继承Thread类创建多线程,优点:代码简单。// 缺点:线程类已经继承Thread类,无法继承其他类,不利于扩展 class MyThread extends Thread{//继承Thread类,重写其中的方法即可实现多线程 //重写run()方法 public void run(){ for (int i = 0; i < 6; i++) { System.out.println("子线程执行:"+i); } }}
创建方式二:实现Runnable接口
class r{ //创建方式二 public static void main(String[] args) { //创建一个任务对象 Runnable r=new MyRunnable(); //把任务对象交给Thread处理 Thread t=new Thread(r); t.start();//调用start()方法启动线程(实际执行的还是run()方法) //注意:子线程一定要放在主线程之前,不然先跑主线程还是会被当做是单线程 for (int i = 0; i < 5; i++) { System.out.println("主线程执行:"+i); } } } //优点:只是实现接口,可以继续继承类和实现接口,扩展性强 // 缺点:多一层对象包装,如果线程有执行结果,是不可以直接返回的class MyRunnable implements Runnable{//实现Runnable接口,重写其中的方法即可实现多线程 public void run(){ for (int i = 0; i < 5; i++) { System.out.println("子线程执行:"+i); } }}
创建方式二的另一种语法形式:
class r_2{ //实现Runnable接口,用匿名内部类的方式(另一种语法形式) public static void main(String[] args) { //原始形态:// Runnable r=new Runnable() {// @Override// public void run() {// for (int i = 0; i { for (int i = 0; i < 5; i++) { System.out.println("子线程执行:"+i); } }).start(); for (int i = 0; i < 5; i++) { System.out.println("主线程执行:"+i); } }}
小案例:
class 案例_售票{ //四个窗口同时售买100张票 public static void main(String[] args) { TicketWindow tw=new TicketWindow();//创建TicketWindow实例化对象 new Thread(tw,"窗口1").start();//创建线程对象并命名为窗口1,开启线程 new Thread(tw,"窗口2").start(); new Thread(tw,"窗口3").start(); new Thread(tw,"窗口4").start(); }}class TicketWindow implements Runnable{ private int tickets=100; public void run(){ while(true){ if(tickets>0) { Thread t = Thread.currentThread();//获取当前线程 String t_name = t.getName();//获取当前线程名字 System.out.println(t_name + "正在发售第\t" + tickets-- + "\t张票");//票售出后--,不然永远卖不完 } if(tickets==0){ break; } } }}
前两种创建方式都有一个共同的缺点,那就是不能返回线程执行结果
于是便有了创建方式三:实现Callable接口
import java.util.concurrent.Callable;import java.util.concurrent.FutureTask;class 创建_返回结果{ public static void main(String[] args)throws Exception{ //创建Callable任务对象 Callable c=new MyCallable(100); //把Callable任务对象交给FutrueTask对象 //FutrueTask对象作用1:是Runnable对象(实现了Runnable接口),可以交给Thread了 //FutrueTask对象作用2:可以在线程执行完毕后调用get方法得到线程执行完毕的结果 FutureTaskf1=new FutureTask(c); //交给线程处理 Thread t1=new Thread(f1); t1.start();//启动线程1 Callable c2=new MyCallable(200); FutureTaskf2=new FutureTask(c2); Thread t2=new Thread(f2); t2.start();//启动线程2 //如果f1任务没有执行完毕,那么这里的代码会等待,直到线程1跑完才提取结果 String str1=f1.get(); System.out.println("第一个线程执行结果为:"+str1); //如果f2任务没有执行完毕,那么这里的代码会等待,直到线程2跑完才提取结果 String str2=f2.get(); System.out.println("第二个线程执行结果为:"+str2); }}//定义一个任务类,实现Callable接口,应该声明线程任务结束后返回的结果的数据类型class MyCallable implements Callable { // v(泛型) private int n; public MyCallable(int n) { this.n = n; } //重写call方法 //案例:加法 public String call() throws Exception { int sum = 0; for (int i = 1; i <=n; i++) { sum += i; } return "子线程执行结果为:" + sum; }}
三种创建多线程方式的优缺点 :