J2SE(9)之多线程(线程的状态、join、yield、sleep)
程序员文章站
2022-05-12 14:53:31
...
1、线程的状态
Java中的线程的生命周期大体可分为5种状态。
1. 新建(NEW):新创建了一个线程对象:new Thread(new Runnable实现类)。
2. 可运行(RUNNABLE):线程对象创建后,其他线程(比如main线程)调用了该对象的start()方法。该状态的线程位于可运行线程池中,等待被线程调度选中,获取cpu 的使用权 。
3. 运行(RUNNING):可运行状态(runnable)的线程获得了cpu 时间片(timeslice) ,执行程序代码。
4. 阻塞(BLOCKED):阻塞状态是指线程因为某种原因放弃了cpu 使用权,即让出了cpu timeslice,暂时停止运行。直到线程进入可运行(runnable)状态,才有机会再次获得cpu timeslice 转到运行(running)状态。阻塞的情况分三种:
(一). 等待阻塞:运行(running)的线程执行o.wait()方法,JVM会把该线程放入等待队列(waitting queue)中。
(二). 同步阻塞:运行(running)的线程在获取对象的同步锁时,若该同步锁被别的线程占用,则JVM会把该线程放入锁池(lock pool)中。
(三). 其他阻塞:运行(running)的线程执行Thread.sleep(long ms)或t.join()方法,或者发出了I/O请求时,JVM会把该线程置为阻塞状态。当sleep()状态超时、join()等待线程终止或者超时、或者I/O处理完毕时,线程重新转入可运行(runnable)状态。
5. 死亡(DEAD):线程run()、main() 方法执行结束,或者因异常退出了run()方法,则该线程结束生命周期。死亡的线程不可再次复生。
参考地址:https://blog.csdn.net/xingjing1226/article/details/81977129
1.1 如何干涉线程的状态以及停止方法
public class StopDemo01 {
public static void main(String[] args) {
Study s =new Study();
new Thread(s).start();
//外部干涉
for(int i=0;i<100;i++){
if(50==i){ //外部干涉
s.stop();
}
System.out.println("main.....-->"+i);
}
}
}
class Study implements Runnable{
//1)、线程类中 定义 线程体使用的标识
private boolean flag =true;
@Override
public void run() {
//2)、线程体使用该标识
while(flag){
System.out.println("study thread....");
}
}
//3)、对外提供方法改变标识
public void stop(){
this.flag =false;
}
}
2、线程的合并,阻塞
1、join :合并线程,调用join方法的线程对象加入到线程队列中,变成单线程了。
2、yield:暂停自己的线程,是static方法。在哪个线程的主体中调用,就是暂停哪个线程。
2.1 join方法
/**
* join:合并线程
*/
public class JoinDemo01 extends Thread {
public static void main(String[] args) throws InterruptedException {
JoinDemo01 demo = new JoinDemo01();
Thread t = new Thread(demo); //新生
t.start();//就绪
//cpu调度 运行
for(int i=0;i<1000;i++){
if(50==i){
t.join(); //把t线程对象加入到main线程,main会阻塞...会先执行完t,才会再次执行main
}
System.out.println("main...."+i);
}
}
@Override
public void run() {
for(int i=0;i<1000;i++){
System.out.println("join...."+i);
}
}
}
2.2 yield方法
public class YieldDemo01 extends Thread {
public static void main(String[] args) {
YieldDemo01 demo = new YieldDemo01();
Thread t = new Thread(demo); //新生
t.start();//就绪
//cpu调度 运行
for(int i=0;i<1000;i++){
if(i%20==0){
//暂停本线程 main
Thread.yield();
}
System.out.println("main...."+i);
}
}
@Override
public void run() {
for(int i=0;i<1000;i++){
System.out.println("yield...."+i);
}
}
}
3、sleep方法
sleep方法不会释放锁对象。
import java.text.SimpleDateFormat;
import java.util.Date;
/**
* 倒计时
* 1、倒数10个数,一秒内打印一个
* 2、倒计时
*/
public class SleepDemo01 {
public static void main(String[] args) throws InterruptedException {
Date endTime =new Date(System.currentTimeMillis()+10*1000);
long end =endTime.getTime();
while(true){
//输出
System.out.println(new SimpleDateFormat("mm:ss").format(endTime));
//等待一秒
Thread.sleep(1000);
//构建下一秒时间
endTime =new Date(endTime.getTime()-1000);
//10秒以内 继续 否则 退出
if(end-10000>endTime.getTime()){
break;
}
}
}
public static void test1() throws InterruptedException{
int num =10;
while(true){
System.out.println(num--);
Thread.sleep(1000); //暂停
if(num<=0){
break;
}
}
}
}
sleep模拟 网络延时 线程不安全的类
/**
* Sleep模拟 网络延时 线程不安全的类
*/
public class SleepDemo02 {
public static void main(String[] args) {
//真实角色
Web12306 web= new Web12306();
Web12306 web2 = new Web12306();
//代理
Thread t1 =new Thread(web,"路人甲");
Thread t2 =new Thread(web,"黄牛已");
Thread t3 =new Thread(web,"攻城师");
//启动线程
t1.start();
t2.start();
t3.start();
}
}
class Web12306 implements Runnable {
private int num =50;
@Override
public void run() {
while(true){
if(num<=0){
break; //跳出循环
}
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+"抢到了"+num--);
}
}
}
4、线程的基本信息
public class MyThread implements Runnable {
private boolean flag =true;
private int num =0;
@Override
public void run() {
while(flag){
System.out.println(Thread.currentThread().getName()+"-->"+num++);
}
}
public void stop(){
this.flag=!this.flag;
}
}
/**
Thread.currentThread() :当前线程
setName():设置名称
getName():获取名称
isAlive():判断状态
*/
public class InfoDemo01 {
public static void main(String[] args) throws InterruptedException {
MyThread it =new MyThread();
Thread proxy =new Thread(it,"挨踢");
proxy.setName("test");
System.out.println(proxy.getName());
System.out.println(Thread.currentThread().getName()); //main
proxy.start();
System.out.println("启动后的状态:"+proxy.isAlive());
Thread.sleep(200);
it.stop();
Thread.sleep(100);
System.out.println("停止后的状态:"+proxy.isAlive());
}
}
线程的优级别:
优先级代表的概率,不是绝对的先后顺序:
/**
* 优先级:概率,不是绝对的先后顺序
MAX_PRIORITY 10
NORM_PRIORITY 5 (默认)
MIN_PRIORITY 1
setPriority()
getPriority()
*/
public class InfoDemo02 {
public static void main(String[] args) throws InterruptedException {
MyThread it =new MyThread();
Thread p1 =new Thread(it,"挨踢1");
MyThread it2 =new MyThread();
Thread p2 =new Thread(it2,"挨踢2");
p1.setPriority(Thread.MIN_PRIORITY); //设置优先级
p2.setPriority(Thread.MAX_PRIORITY);//设置优先级
p1.start();
p2.start();
Thread.sleep(100);
it.stop();
it2.stop();
}
}
上一篇: Android 日志错误收集