最新消息: USBMI致力于为网友们分享Windows、安卓、IOS等主流手机系统相关的资讯以及评测、同时提供相关教程、应用、软件下载等服务。

五:多线程深入话题

互联网 admin 3浏览 0评论

五:多线程深入话题

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 blocke.printStackTrace();}System.out.println(Thread.currentThread().getName() + "正在运行,num=" + num++);}}, "执行线程").start();// 让线程运行200msThread.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 blocke.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 blocke.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无法描述同步的处理,是一种直接内存的处理,避免了副本的操作是实现同步操作的

 

五:多线程深入话题

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 blocke.printStackTrace();}System.out.println(Thread.currentThread().getName() + "正在运行,num=" + num++);}}, "执行线程").start();// 让线程运行200msThread.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 blocke.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 blocke.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无法描述同步的处理,是一种直接内存的处理,避免了副本的操作是实现同步操作的

 

与本文相关的文章

发布评论

评论列表 (0)

  1. 暂无评论