Java-----多线程(中)

线程在一定条件下,状态会发生变化。线程变化的状态转换图如下:



1、新建状态(New):新创建了一个线程对象。
2、就绪状态(Runnable):线程对象创建后,其他线程调用了该对象的start()方法。该状态的线程位于可运行线程池中,变得可运行,等待获取CPU的使用权。
3、运行状态(Running):就绪状态的线程获取了CPU,执行程序代码。
4、阻塞状态(Blocked):阻塞状态是线程因为某种原因放弃CPU使用权,暂时停止运行。直到线程进入就绪状态,才有机会转到运行状态。阻塞的情况分三种:
(一)、等待阻塞:运行的线程执行wait()方法,JVM会把该线程放入等待池中。
(二)、同步阻塞:运行的线程在获取对象的同步锁时,若该同步锁被别的线程占用,则JVM会把该线程放入锁池中。
(三)、其他阻塞:运行的线程执行sleep()或join()方法,或者发出了I/O请求时,JVM会把该线程置为阻塞状态。当sleep()状态超时、join()等待线程终止或者超时、或者I/O处理完毕时,线程重新转入就绪状态。
5、死亡状态(Dead):线程执行完了或者因异常退出了run()方法,该线程结束生命周期。


class MyThread implements Runnable{

	public void run() {
		for (int i=1; i<=3; i++) {			
			System.out.println(Thread.currentThread().getName());
		}
	}
}
public class lzwCode {
	
	public static void main(String [] args) {
		MyThread my = new MyThread();
		new Thread(my, "线程A").start();
		new Thread(my, "线程B").start();
		new Thread(my).start();
	}
}

控制台结果:

说明如果我们没有指定名字的话,系统自动提供名字。

提醒一下大家:main方法其实也是一个线程。在java中所以的线程都是同时启动的,至于什么时候,哪个先执行,完全看谁先得到CPU的资源。

 在java中,每次程序运行至少启动2个线程。一个是main线程,一个是垃圾收集线程。因为每当使用java命令执行一个类的时候,实际上都会启动一个JVM,每一个jVM实习在就是在操作系统中启动了一个进程。



判断线程是否启动
class MyThread implements Runnable{

	public void run() {
		for (int i=1; i<=3; i++) {			
			System.out.println(Thread.currentThread().getName());
		}
	}
}
public class lzwCode {
	
	public static void main(String [] args) {
		MyThread my = new MyThread();
		Thread th = new Thread(my);
		System.out.println("线程启动前:"+ th.isAlive()); //判断线程是否启动
		th.start();
		System.out.println("线程启动前:"+ th.isAlive());
	}
}

控制台结果:

主线程也有可能在子线程结束之前结束。并且子线程不受影响,不会因为主线程的结束而结束。


线程的强制执行join():

package com.demo;
public class lzwCode implements Runnable{

	public void run() {
		for (int i=1; i<=3; i++) {			
			System.out.println(Thread.currentThread().getName());
		}
	}

	public static void main(String [] args) {
		lzwCode my = new lzwCode();
		Thread th = new Thread(my, "线程A");
		th.start();
		for (int i=0; i<=10; i++) {
			if (i > 5) {
				try{
					th.join(); //强制执行线程th
				} catch(Exception e) {
					e.printStackTrace();
				}
			}
			System.out.println("main 线程执行==>"+i);
		}
	}
}

控制台并不是每一次都会出现如下结果:


再看一个列子:

public class lzwCode implements Runnable{

    private static int a = 0;
	
	public void run() {
		for (int i=0; i<5; i++) {			
			a++;
		}
	}

	public static void main(String [] args) {
		Runnable my = new lzwCode();
		Thread th = new Thread(my);
		th.start();
		System.out.println(a);
	}
}
请问程序的输出结果是5吗?答案是:有可能。其实你很难遇到输出5的时候,通常情况下都不是5,几乎都是0。当然这也和机器有严重的关系。为什么呢?我的解释是当主线程main方法执行System.out.println(a);这条语句时,线程还没有真正开始运行,或许正在为它分配资源准备运行吧。因为为线程分配资源需要时间,而main方法执行完t.start()方法后继续往下执行System.out.println(a);,这个时候得到的结果是a还没有被改变的值0。怎样才能让输出结果为5!其实很简单,join()方法提供了这种功能。join()方法,它能够使调用该方法的线程在此之前执行完毕


public class lzwCode implements Runnable{

    private static int a = 0;
	
	public void run() {
		for (int i=0; i<5; i++) {			
			a++;
		}
	}

	public static void main(String [] args) {
		Runnable my = new lzwCode();
		Thread th = new Thread(my);
		th.start();
		try{
			th.join();
		}
		catch (Exception e){
			e.printStackTrace();
		}	
		System.out.println(a);
	}
}

这个时候,程序输入结果始终为5。


为了证明如果不使用th.join()方法,主线程main方法的System.out.println(a);语句将抢先执行,我们可以在main方法中加入一个循环,这个循环用来延长main方法执行的时间,循环次数将严重取决于机器性能。如果循环次数得当,我们也可以看到a的输出结果是5。


package com.demo;

public class lzwCode implements Runnable {
	
	public static int a = 0;

	public void run() {
		for (int i = 0; i < 5; i++) {
			a++;
		}
	}

	public static void main(String[] args) throws Exception {
		Runnable r = new lzwCode();
		Thread th = new Thread(r);
		th.start();
		for (int i = 0; i < 300; i++) {
			System.out.println(i);
		}
		System.out.println();
		System.out.println(a);
	}
}

这时,在我的机器上,a的输出值始终为5。

线程的休眠sleep():


public class lzwCode implements Runnable{

    private static int a = 0;
	
	public void run() {
		for (int i=0; i<3; i++) {			
			try	{
				Thread.sleep(3000); //线程每隔3s执行
			} catch (Exception e) {
				e.printStackTrace();
			}
			System.out.println(Thread.currentThread().getName()+i);
		}
	}

	public static void main(String [] args) {
		Runnable my = new lzwCode();
		Thread th = new Thread(my, "线程睡觉");
		th.start();
	}
}

【运行结果】:(结果每隔3s输出一个)

线程睡觉0

线程睡觉1

线程睡觉2

 

线程的中断interrupt():

public class lzwCode implements Runnable {

	public void run() {
		System.out.println("执行run方法");
		try {
			Thread.sleep(10000);
			System.out.println("线程完成休眠");
		} catch (Exception e) {
			System.out.println("休眠被打断");
			return; //返回到程序的调用处  
		}
		System.out.println("线程正常终止");
	}

	public static void main(String[] args) {
		lzwCode lc = new lzwCode();
		Thread demo = new Thread(lc, "线程");
		demo.start();
		try {
			Thread.sleep(2000);
		} catch (Exception e) {
			e.printStackTrace();
		}
		demo.interrupt(); //2s后中断线程  
	}
} 

【运行结果】:2秒后线程中断

执行run方法

休眠被打断


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值