博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Java多线程学习(1)创建线程与线程的生命周期
阅读量:5845 次
发布时间:2019-06-18

本文共 2964 字,大约阅读时间需要 9 分钟。

多线程之前学过,很久没用忘得差不多了,重新学习一下,然后再看《Java并发编程的艺术》。

一、进程与线程

计算机同时运行多个程序,每个运行中的程序就是一个进程。每一个进程内部又有多个线程。

进程有如下三个特征:
(1)独立性:它可以有自己独立的资源,有自己的私有地址空间;
(2)动态性:进程是一个在系统中活动的指令集合,具有自己的生命周期和不同的状态;
(3)并发性:多个进程可以在单个处理器上并发执行。

并发性与并行性:

(1)并发指在同一时刻只有一条指令执行,处理器快速切换多个进程指令;
(2)并行性指在同一时刻,有多条指令在多个处理器上同时执行。
现代操作系统都支持多进程的并发,常用方式有:共用式多任务操作策略和抢占式多任务操作策略。

二、创建线程的方式

1、继承Thread类

1)继承Thread类,并重新写run()方法;
2)创建上述类的实例,即创建线程对象;
3)调用start()方法启动线程。

public class FirstThread extends Thread {	private int i=0;	public void run() {		for(;i<100;++i) {			System.out.println(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.currentThread()是Thread类的静态方法,返回当前正在执行的线程对象; getName()是Thread类的实例方法,返回调用该方法的线程的名字。

2、实现Runnable接口

1)定义Runnable接口的实现类,重写run()方法 2)创建Runnable实现类的实例,并作为Thread类的target来创建Thread对象,该Thread对象才是真正的线程对象。
可以在创建Thread类对象的时候为该对象取一个名字:new Thread(secondThread,"线程2");
public class SecondThread implements Runnable {

private int i = 0;	@Override	public void run() {		for (; 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 st1 = new SecondThread();				new Thread(st1,"new-1").start();				new Thread(st1,"new-2").start();			}		}	    }       }复制代码

Runnable接口是函数式接口,可以使用Lambda表达式创建Runnable对象。

上面代码中,多个线程共享了一个target。

3、使用Callable和Future创建线程

Callable像是Runnable的增强版:
call()方法可以有返回值;
call()方法可以声明,抛出异常。
Java5提供了Future接口来代表Callable接口中call()方法的返回值。它有FutureTask实现类,该类实现了Future接口和Runnable接口,可以作为Thread类的Target。
该方法创建线程的步骤:
1)创建Callable接口的实现类,并实现call()方法,call方法为线程执行体,可以有返回值。再创建Callable的实例。
2)使用FutureTask类来包装Callable对象。
3)使用FutureTask对象作为Thread对象的target创建并启动线程。
4)可以使用FutureTask类的get()方法来获得子线程执行结束后的返回值。

public class ThirdThread {public static void main(String[] args) {	ThirdThread rt = new ThirdThread();	FutureTask
task = new FutureTask
((Callable
)()-> { 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(); }}}复制代码

三、线程的生命周期

在线程的生命周期中,要经过:新建、就绪、运行、阻塞、死亡5种状态。

当使用new关键字创建了一个线程后,该线程就处于新建状态。(此时还没有表现出来线程的动态特性);当调用start()方法后,线程处于就绪状态,JVM会为其创建方法调用栈和程序计数器;当就绪状态的线程获得了CPU资源,开始执行run()方法,此时处于运行状态;当发生如下情况时,程序处于阻塞状态:
1线程调用sleep()方法主动放弃处理器资源;
2该线程视图获得一个同步监视器,但是该监视器被其他线程持有;
3线程在等待通知notify
4调用了线程的suspend()方法将线程挂起。
而当sleep了指定时间;获得了同步监视器;其他线程发出了通知;挂起的线程被调用了resume()的方法,时可以解除阻塞,让线程重写处于就绪状态。
当:1run或call方法执行完成;2线程抛出异常或error;3直接调用stop()方法结束该线程(容易死锁),该线程死亡。

转载地址:http://pshcx.baihongyu.com/

你可能感兴趣的文章
加热炉简是新来的整个系统的板
查看>>
Mockito使用注意事项
查看>>
[LeetCode] Palindrome Linked List 回文链表
查看>>
UVA - 825Walking on the Safe Side(dp)
查看>>
评论:人才流失强力折射出现实畸形人才观
查看>>
虚拟运营商10月或大面积放号 哭穷背后仍有赢家
查看>>
UML中关联,组合与聚合等关系的辨析
查看>>
ios的google解析XML框架GDataXML的配置及使用
查看>>
netty-当一个客户端连接到来的时候发生了什么
查看>>
在51CTO三年年+了,你也来晒晒
查看>>
js控制图片等比例缩放
查看>>
Openstack API常用命令
查看>>
关于k-means聚类算法的matlab实现
查看>>
跟随我在oracle学习php(8)
查看>>
UVA-10212 The Last Non-zero Digit. 分解质因子+容斥定理
查看>>
求两个集合的交集,并集,差集
查看>>
Kotlin的语法糖(一)基础篇
查看>>
亚信安全参加第六届全国等保技术大会 态势感知助力“等保2.0”落地
查看>>
大数据公司Palantir融得7亿美元 曾追踪拉登
查看>>
建立备份策略的重要性
查看>>