多线程的创建java

方法1:继承Thread类

1定义一个子类继承线程类java.long.Thread ,重写run()方法

2创建一个子类对象

3 调用线程对象的start方法启动线程(启动后还是执行run方法)

第一种方法

public class MyThread extends Thread {
	@Override
	//run方法里面写要执行的东西
	public void run() {
		// TODO Auto-generated method stub
		super.run();
		for(int i=0;i<5;i++) {
			System.out.println("子线程"+i);
		}
	
	}

}
第一种方法
public class Test1 {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		Thread t=new MyThread();//创建线程对象
		t.start();//调用线程的启动方法
		for(int i=0;i<5;i++) {
			System.out.println("主线程"+i);
		}
		

	}

}

方式1的优缺点?

优点编码简单

缺点:存在单继承的局限性,线程类已经继承了Thread,无法继承其他类,不利于扩展

为什么不直接调用run方法,而是调用strat启动线程?

直接调用run方法会当成普通方法执行,此时相当于还是单线程

只有调用start方法才是启动一个新的线程执行

为什么不能把主线程任务放在子线程之前?

这样主线程一直就是先跑完的,相当于一个单线程的效果了

多线程的创建方式二(实现Runnable接口)

1定义一个线程任务类MyRunnable实现Runnable接口,重新run方法

2创建一个MyRunnable任务对象

3把任务对象交给 Thread线程对象处理

4调用线程对象的start()方法启动线程

Thread构造器

public Thread(String name) 可以为当前线程指定名称

public Thread (Runnable target)  封装Runnable对象成线程对象

Public Thread (Runnable target, String name )封装Runnable 对象成线程对象并指定线程名称

//第二种方法

public class MyRunnable  implements Runnable{
	@Override
	//写线程任务
	public void run() {
		// TODO Auto-generated method stub
		for(int i=0;i<5;i++) {
			System.out.println("子线程被执行"+i);
		}
	}

}

package 多线程;

public class Test2 {
//第二种方法

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		Runnable r=new MyRunnable(); //创建任务对象
		Thread t=new Thread(r);//封装成线程对象
		t.start(); //启动线程
		for(int i=0;i<5;i++) {
			System.out.println( "主线程被执行"+i);
		}
		

	}

}

方式二优缺点

优点:线程任务类只实现了接口,可以继续继承类和实现接口扩展性强

缺点:编程多一层对象包装,如果线程有执行结果不可以直接返回的

线程创建方式2(匿名内部类写法)

//第二种方式的匿名内部类写法

public class Test5 {

	public static void main(String[] args) {
		Thread t=new Thread(new Runnable() {
			
			@Override
			public void run() {
				for(int i=0;i<5;i++) {
					System.out.println("子线程"+i);
				}
				
			}
		});
		t.start();
		for(int i=0;i<5;i++) {
			System.out.println("主线程被执行"+i);
		}
	}

}

可以用Lamubda表达式继续简化为

		Thread t=new Thread(()-> {
				for(int i=0;i<5;i++) {
					System.out.println("子线程"+i);
				}		
		});

前两种创建方式都存在一个问题?

他们重写的run方法均不能直接返回结果

不适合需要返回线程执行结果的业务场景

怎么解决这个问题呢?

JDK5.0提供了Callable和FutureTask来实现

第三种方式:利用Callable、FutureTask接口实现

1得到任务对象 定义类实现Callable接口,重写call方法,封装要做的事情;用FutureTask把Callable对象封装成线程对象

2把线程对象交给Thread处理

3调用Thread的start方法启动线程,执行任务

4线程执行完毕,通过FutureTask的get方法获取任务执行的结果

//第三种方式

import java.util.concurrent.Callable;

public class Threesum  implements Callable<Integer>{
	private int a;
	private int b;
	
	public Threesum(int a, int b) {
		super();
		this.a = a;
		this.b = b;
	}

	//写要执行的任务
	//我的功能是求和
	@Override
	public Integer call() throws Exception {
		// TODO Auto-generated method stub
		int sum=a+b;
		return sum;
	}

}

主函数

//第三种方式

import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;

public class Test6 {

	public static void main(String[] args) {
		// 创建Callable对象
		Callable<Integer> ca=new Threesum(10,20); 
		//把Callable 对象包装为 FutureTask对象
		FutureTask<Integer> fu=new FutureTask<>(ca);
		//FutureTask交给线程对象Thread
		Thread s=new Thread(fu);
		//开始执行
		s.start(); 
		//看结果用FutureTask的get方法
		try {
			int sum=fu.get();
			System.out.println("第三种方法写的线程输出结果为:"+sum);
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (ExecutionException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
		

	}

}

方式三优缺点

优点:线程任务类只是实现接口,可以继续继承和实现接口,扩展性强

可以在线程执行完毕后去获取线程执行的结果

缺点:代码复杂一点

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小萌新上大分

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值