五:多线程深入话题

1、优雅的停止线程

          在多线程操作之中,启动多线程使用的是Thread类中的start()方法,而要对多线程进行停止处理,在原来的Thread类中提供有stop()方法,但此方法在JDK1.2版本之后就已经过期了,不可使用。而除了stop()方法之外,以下几个方法也被禁用了:

方法方法定义废除原因
停止多线程
public final void stop​()
这些方法的使用可能导致线程的死锁
销毁多线程
public void destroy​()
挂起线程(暂停执行)
public final void suspend​()
恢复执行(恢复挂起的线程执行)
public final void resume​()

          在不使用上面方法的情况下,我们可以使用另外一种柔和的方式来让线程停止。

          范例:线程的停止

package cn.demos;

public class ThreadDemo {
	public static boolean flag = true;

	public static void main(String[] args) throws Exception {
		new Thread(() -> {
			long num = 0;
			while (flag) {
				try {
					//运行一次休眠50s,总共运行4次
					Thread.sleep(50);
				} catch (Exception e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}

				System.out.println(Thread.currentThread().getName() + "正在运行,num=" + num++);
			}
		}, "执行线程").start();
		// 让线程运行200ms
		Thread.sleep(200);
		flag = false;// 停止线程
	}

}

          从上面程序可以分析出,整个程序的运行与flag的值有关,线程总共运行200ms,而每次线程运行一次则休眠50ms,其执行结果为执行4次,利用休眠时间设置线程停止运行。

          而万一现在有其他的线程去控制这个flag的内容,那么线程的停止会受到影响,程序需要通过对flag值的判断

来执行。

 

2、后台守护线程

          在多线程程序里面,可以进行守护线程的定义。假如现在程序里主线程的程序或者其他线程还在执行,那么守护线程将一直存在,并且运行在后台状态。

          而在Thread类中提供有如下的守护线程的操作方法:

 方法定义

设置为守护线程

public final void setDaemon​(boolean on)
判断是否为守护线程
public final boolean isDaemon​()

          范例:使用守护线程

package cn.demos;

public class ThreadDemo {
	public static boolean flag = true;

	public static void main(String[] args) throws Exception {
		// 用户线程
		Thread useThread = new Thread(() -> {
			for (int x = 0; x < Integer.MAX_VALUE; x++) {
				// 添加延迟
				try {
					Thread.sleep(100);
				} catch (Exception e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
				System.out.println(Thread.currentThread().getName() + "用户线程正在执行,x=" + x);
			}

		}, "用户线程");// 完成核心任务

		// 守护线程
		Thread daemoThread = new Thread(() -> {
			for (int x = 0; x < Integer.MAX_VALUE; x++) {
				try {
					Thread.sleep(100);
				} catch (Exception e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
				System.out.println(Thread.currentThread().getName() + "守护线程正在执行,x=" + x);
			}

		}, "守护线程");// 完成核心任务
		// 设置守护线程
		daemoThread.setDaemon(true);

		// 先启动用户线程,然后启动守护线程
		useThread.start();
		daemoThread.start();
	}

}

          从程序执行结果中可以得知,所有的守护线程都是围绕在用户线程的周围,所以,如果程序执行完毕那么守护线程也会消失。而在整个JVM最大的守护线程就是GC线程。

          程序执行过程中GC线程会一直存在,如果程序执行完毕,那么GC线程也将消失。

 

3、volatile关键字

          在程序定义中,volatile关键字主要是在属性定义上使用的,即表示此属性为直接数据操作,而不进行副本的拷贝处理。

         

          在正常进行变量处理的时候往往会经历如下的步骤:

                    1)获取变量原有的数据内容副本;

                    2)利用副本为变量进行数学计算;

                    3)将计算后的变量,保存到原始空间之中;

          若,在属性上追加volatile关键字,表示的就是不使用副本,而是直接操作原始变量,相当于节约了:拷贝副本、重新保存的步骤。

          面试题:请解释volatile与synchronized的区别:

区别volatilesynchronized
1主要在属性上使用在代码块与方法上使用的
2无法描述同步的处理,是一种直接内存的处理,避免了副本的操作是实现同步操作的

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值