java 多线程的三种构建方法
作者:lqh 发布时间:2023-07-01 22:18:26
java 多线程的三种构建方法
继承Thread类创建线程类
public class Thread extends Object implements Runnable
定义Thread类的子类,并重写其run()方法
创建Thread子类的实例,即创建了线程对象
调用线程对象的start()方法启动线程
public class FirstThread extends Thread {
public void run(){
for(int i=0;i<100;i++){
/*
* Thread类已经继承了Object
* Object类创建了name选项 并且有其getName(),setName()方法
* 在继承Thread的类里面使用时只需要用this引用
*/
System.out.println(this.getName()+" "+i);
}
}
public static void main(String[] args) {
for(int i=0;i<100;i++){
System.out.println(Thread.currentThread().getName()+" "+i);
if(i==20){
new FirstThread().start();
new FirstThread().start();
}
}
}
}
Thread类已经继承了Object
Object类创建了name选项 并且有其getName(),setName()方法
在继承Thread的类里面使用时只需要用this引用
上面两个副线程和主线程随机切换,又因为使用的是继承Thread的类所以两个副线程不能共享资源
start()方法调用后并不是立即执行多线程代码,而是使得该线程编程可运行状态,什么时候运行是由操作系统决定的
实现Runnable接口创建线程类
public Thread()
public Thread(Runnable target)
public Thread(Runnable target,String name)
定义Runnable接口的实现类,并重写该接口的run()方法
创建Runnable实现类的实例,并以此作为Thread的target来创建Thread对象,该Thread对象才是真正的线程对象。
public class SecondThread implements Runnable {
public void run(){
for(int i=0;i<100;i++){
System.out.println(Thread.currentThread().getName()+" "+i);
}
}
public static void main(String[] args) {
for(int i=0;i<100;i++){
System.out.println(Thread.currentThread().getName()+" "+i);
if(i==20){
SecondThread st=new SecondThread();
//通过new Thread(target,name)创建线程
new Thread(st,"新线程1").start();
new Thread(st,"新线程2").start();
}
}
}
}
上面的结果是两个副线程和主线程随机切换,但是并没有共享资源,因为他们根本没有能用来共享的资源。
start()方法调用后并不是立即执行多线程代码,而是使得该线程编程可运行状态,什么时候运行是由操作系统决定的
继承Thread类和创建Runnable接口的共享资源详解
在只有可以用来共享的资源时候,也就是同用一个实例化对象。两个创建方式在共享资源时才会有所区别,否则它们都不会共享资源共享资源通常用private static 修饰符来修饰。
class Thread1 extends Thread{
private int count=5;
private String name;
public Thread1(String name) {
this.name=name;
}
public void run() {
for (int i = 0; i < 5; i++) {
System.out.println(name + "运行 count= " + count--);
try {
sleep((int) Math.random() * 10);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
public class Main {
public static void main(String[] args) {
Thread1 mTh1=new Thread1("A");
Thread1 mTh2=new Thread1("B");
mTh1.start();
mTh2.start();
}
}
B运行 count= 5
A运行 count= 5
B运行 count= 4
B运行 count= 3
B运行 count= 2
B运行 count= 1
A运行 count= 4
A运行 count= 3
A运行 count= 2
A运行 count= 1
正是因为有了private int count=5;一句才有了共享资源,但这是继承Thread类的子类,并不能共享资源
class Thread2 implements Runnable{
private int count=15;
public void run() {
for (int i = 0; i < 5; i++) {
System.out.println(Thread.currentThread().getName() + "运行 count= " + count--);
try {
Thread.sleep((int) Math.random() * 10);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
public class Main {
public static void main(String[] args) {
Thread2 my = new Thread2();
new Thread(my, "C").start();//同一个mt,但是在Thread中就不可以,如果用同一个实例化对象mt,就会出现异常
new Thread(my, "D").start();
new Thread(my, "E").start();
}
}
C运行 count= 15
D运行 count= 14
E运行 count= 13
D运行 count= 12
D运行 count= 10
D运行 count= 9
D运行 count= 8
C运行 count= 11
E运行 count= 12
C运行 count= 7
E运行 count= 6
C运行 count= 5
E运行 count= 4
C运行 count= 3
E运行 count= 2
同样的正是因为有了private int count=15这个共同的实例化对象,实现Runnable的类才可以共享资源
那么为什么继承Thread类的子类实现Runable接口的类在共享资源时有区别呢?
因为Java中只能支持单继承,单继承特点意味着只能有一个子类去继承 而Runnabl接口后可以跟好多类,便可以进行多个线程共享一个资源的操作
使用Callable和Future创建线程
Callable怎么看起来都像Runnable接口的增强版,Callable有一个call()方法相当于Runnable的run()方法,但是功能却更加强大:
call()方法可以有返回值
call()方法可以声明抛出异常
Callable接口有泛型限制,Callable接口里的泛型形参类型与call()方法的返回值类型相同。 而且Callable接口是函数式接口,因此可使用Lambda表达式创建Callable对象 Runnable接口也是函数式接口,因此也可以使用Lambda表达式创建Runnable对象
创建Callable接口的实现类,并实现call()方法,该call()方法将作为线程执行体,再创建Callable实现类的实例
使用FutureTask类来包装Callable对象,该FutureTask对象封装了该Callable对象的call()方法
使用FutureTask类对象作为Thread对象的target创建并启动新线程
调用FutureTask对象的get()方法来获得子线程结束后的返回值
public class ThirdThread implements Callable<Integer> {
public Integer call(){
int i=0;
for(;i<100;i++){
System.out.println(Thread.currentThread().getName()+" "+i);
}
return i;
}
public static void main(String[] args){
ThirdThread tt=new ThirdThread();
FutureTask<Integer> task=new FutureTask<>(tt);
Thread t=new Thread(task,"有返回值的线程");
for(int i=0;i<100;i++){
System.out.println(Thread.currentThread().getName()+" "+i);
if(i==20){
t.start();
}
}
try{
System.out.println("返回值是:"+task.get());
}catch(Exception e){
e.printStackTrace();
}
}
}
使用Lambda表达式的Callable和Future创建的线程
public class ThirdThread{
public static void main(String[] args){
ThirdThread tt=new ThirdThread();
//先使用Lambda表达式创建Callable<Integer>对象
//使用FutureTask封装Callable对象
FutureTask<Integer> task=new FutureTask<Integer>((Callable<Integer>)()->{
int i=0;
for(;i<100;i++){
System.out.println(Thread.currentThread().getName()+"的循环变量i的值:"+i);
}
return i;
});
for(int i=0;i<100;i++){
System.out.println(Thread.currentThread().getName()+"的循环变量i的值:"+i);
if(i==20){
new Thread(task,"有返回值的线程").start();
}
}
try{
System.out.println("子线程的返回值"+task.get());
}catch(Exception e){
e.printStackTrace();
}
}
}
如有疑问请留言或者到本站社区交流讨论,感谢阅读,希望能帮助到大家,谢谢大家对本站的支持!
来源:http://blog.csdn.net/gailyyelp/article/details/77969652


猜你喜欢
- 1. 全部Activity可继承自BaseActivity,便于统一风格与处理公共事件,构建对话框统一构建器的建立,万一需要整体变动,一处修
- 在使用EF查询数据的时候,我们常用的查询数据方式有linq to sql,linq to object,查询返回的结果有两种类型:IQuer
- 关于Retrofit的学习,我算是比较晚的了,而现在Retrofit已经是Android非常流行的网络请求框架了。之前,我没有学过Retro
- 介绍一款简洁实用的图片编辑器,纯dart开发。支持:涂鸦、旋转&翻转、马赛克、添加文字,及自定义ui风格。功能演示涂鸦旋转&
- android系统提供了Environment.getExternalStorageDirectory()接口获得存储器的路径,但是这个接口
- 场景做为一个码农,大部分都集中在一二线城市,所以租房也就无可避免,面对如今五花八门的租房信息,往往很难找到合适的房子。而如今的这些租房软件,
- 新建两个工程,一个客户端,一个服务端,先启动服务端再启动客户端两个工程的读写操作线程类基本上完全相同服务端:import java.io.B
- 本文实例为大家分享了Unity3D选择本地图片并加载的具体代码,供大家参考,具体内容如下①找到System.Windows.Forms.dl
- 前言:synchronized 在 JDK 1.5 之前性能是比较低的,在那时我们通常会选择使用 Lock 来替代 synchronized
- 本文实例为大家分享了Android实现类似微信视频接听的具体代码,供大家参考,具体内容如下1、背景需求:业务需要接入视频审核功能,在PC 端
- 本文实例讲述了Android获取手机屏幕大小的方法。分享给大家供大家参考,具体如下:这里主要用了三个对象TextView ,Button ,
- 一、前言在日常工作中,如果涉及到与第三方进行接口对接,有的会使用WebService的方式,这篇文章主要讲解在.NET Framework中
- Android 破解视频App去除广告功能作为一个 * 丝程序猿也有追剧的时候,但是当打开视频app的时候,那些超长的广告已经让我这个 * 丝无法忍
- 内存模型Flink可以使用堆内和堆外内存,内存模型如图所示:flink使用内存划分为堆内内存和堆外内存。按照用途可以划分为task所用内存,
- 在说明映射文件规则之前,先来回顾一下ORM相关概念。1.ORM概念ORM(Object Relationship Mapping)对象关系映
- this可能是几乎所有有一点面向对象思想的语言都会引用到的变量,java自然不例外。只是,this有多少种用法,我也不知道了,让我们来see
- ThreadLocal是什么?该类提供了线程局部 (thread-local) 变量。这些变量不同于它们的普通对应物,因为访问某个变量(通过
- 一般情况下在Word中输入的文字都是横向的,今天给大家分享两种方法来设置/更改一个section内的所有文本的方向及部分文本的方向,有兴趣的
- 在idea下新建一个maven项目,在学习mybaties时跟着视频教程添加依赖发现可以配置maven然后自动导入,这样可以省事不用手写。前
- 前言:微信公众号提供了用户和用户组的管理,我们可以在微信公众号官方里面进行操作,添加备注和标签,以及移动用户组别,同时,微信公众号提供了相应