软件世界网 购物 网址 三丰软件 | 小说 美女秀 图库大全 游戏 笑话 | 下载 开发知识库 新闻 开发 图片素材
多播视频美女直播
↓电视,电影,美女直播,迅雷资源↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
移动开发 架构设计 编程语言 Web前端 互联网
开发杂谈 系统运维 研发管理 数据库 云计算 Android开发资料
  软件世界网 -> 互联网 -> 线程常用操作 -> 正文阅读

[互联网]线程常用操作


本文讲解了Java中中断线程的概念和常用方法以及让步操作和优先级等概念,对线程的常用操作进行初步了解。

1 停止线程


Java停止一个线程是通过调用Thread类的interrupt()方法来实现的,下面具体讲一下它的相关用法。

1.1 interrupt() != 立即终止


调用interrupt()并不会像break语句那样直接就终止线程,它仅仅是在当前线程中打了一个停止的标记,并不是真的停止线程。
国际惯例,上栗子:
自定义线程类
package com.trigl.concurrent.simplethread;

/**
 * 用于讲解interrupt()方法的线程类
 * @author 白鑫
 * @date 2016年3月31日 上午11:39:04
 */
public class InterruptThread extends Thread {
    @Override
    public void run() {
        super.run();
        for (int i = 0; i < 500000; i++) {
            System.out.println("i=" + (i + 1));
        }
    }
}

测试方法
    /**
     * 先让线程启动,线程会打印50万条数据,会花费一定时间。
     * 所以让test方法休眠1秒,再停止线程。
     * @throws InterruptedException
     */
    @Test
    public void testInterruptThread() throws InterruptedException {
        InterruptThread thread = new InterruptThread();
        thread.start();
        Thread.sleep(1000);
        thread.interrupt();
        System.out.println("end");
    }

输出结果
[img]http://img.blog.csdn.net/20160401205732794
从结果看并没有打印到i=500000,貌似是interrupt()方法起作用了,其实非也,关键在:
Thread.sleep(1000);

这条代码上,它将当前test方法的线程休眠了1秒钟,在这一秒中之内线程thread打印到了图中所示的最后一条i=123878,然后test方法执行完毕了就结束了,而thread线程还在后台执行,只不过由于test方法结束了,所以不再打印到控制台上。如果我们将休眠时间改为10秒,即改为:
Thread.sleep(10000);

再来看一下结果:
[img]http://img.blog.csdn.net/20160401205835310
可以看到,50万条数据全部打印了出来,所以interrupt()方法并没有起作用。那么问题来了,到底怎么才能真的停止线程呢?

1.2 判断线程是否是停止状态


在介绍如何停止线程之前,首先看一下如何判断线程的停止状态。Thread类提供了两种方法:
  • public static boolean interrupted() // 测试当前线程是否已经中断
  • public boolean isInterrupted() // 测试线程是否已经中断

1.2.1 interrupted()


interrupted()是一个静态方法,通过
Thread.interrupted();

来直接直接调用,它判断的是当前正在执行的线程的中断状态,上栗子:
测试方法
    /**
     * 测试Thread的interrupted()方法
     */
    @Test
    public void testInterrupted() {
        Thread.currentThread().interrupt();
        System.out.println("Thread.interrupted()" + Thread.interrupted());
        System.out.println("Thread.interrupted()" + Thread.interrupted());
        System.out.println("end");
    }

输出结果
Thread.interrupted()=true
Thread.interrupted()=false
end

结果很奇怪,明明是两条相同的代码,为什么结果一个是true一个是false呢?
从官方API中找答案:

boolean java.lang.Thread.interrupted()
Tests whether the current thread has been interrupted. The interrupted status of the thread is cleared by this method. In other words, if this method were to be called twice in succession, the second call would return false (unless the current thread were interrupted again, after the first call had cleared its interrupted status and before the second call had examined it).
A thread interruption ignored because a thread was not alive at the time of the interrupt will be reflected by this method returning false.

说的很明白:如果连续两次调用该方法,则第二次调用将返回false(除非正好在第二次调用前当前线程又中断了一次);如果线程已经不再存活(not alive),那么将忽略中断状态标记,调用该方法会返回false。

1.2.2 isInterrupted()


该方法判断的是一个Thread对象的中断状态,而不是当前线程的中断状态。上栗子来比较与interrupted()方法的不同:
测试方法
    /**
     * 测试Thread的isInterrupted()方法
     * @throws InterruptedException 
     */
    @Test
    public void testIsInterrupted() throws InterruptedException {
        InterruptThread thread = new InterruptThread();
        thread.start();
        thread.interrupt();
        System.out.println("thread.isInterrupted()=" + thread.isInterrupted());
        System.out.println("thread.isInterrupted()=" + thread.isInterrupted());
        System.out.println("end");
    }

输出结果
thread.isInterrupted()=true
i=1
thread.isInterrupted()=true
end
i=2
i=3
......

从结果中可以看到,方法isInterrupted()并未清除状态标志,所以打印了两个true。

1.3 使用异常法停止线程


具体实现就是在一个自定义线程类的run方法中,首先判断一下线程是否是停止状态,如果是停止状态,则手动抛出一个InterruptedException异常来中断线程,实例如下:
自定义线程类
package com.trigl.concurrent.simplethread;

/**
 * 使用异常法停止线程
 * @author 白鑫
 * @date 2016年3月31日 上午11:39:04
 */
public class InterruptThread extends Thread {
    @Override
    public void run() {
        super.run();
        try {
            for (int i = 0; i < 500000; i++) {
                if (Thread.interrupted()) {
                    System.out.println("已经是停止状态了!我要退出了!");
                    throw new InterruptedException();
                }
                System.out.println("i=" + (i + 1));
            }
            System.out.println("如果你能看到我说明线程并没有真的被中断!");
        } catch (Exception e) {
            // TODO: handle exception
            System.out.println("进入到InterruptThread类run方法中的catch了!");
            e.printStackTrace();
        }
    }
}

测试方法
    @Test
    public void testInterruptThread() throws InterruptedException {
        InterruptThread thread = new InterruptThread();
        thread.start();
        Thread.sleep(1000);
        thread.interrupt();
        System.out.println("end");
    }

输出结果
......
i=121981
i=121982
i=121983
end
已经是停止状态了!我要退出了!
进入到InterruptThread类run方法中的catch了!
java.lang.InterruptedException
    at com.trigl.concurrent.simplethread.InterruptThread.run(InterruptThread.java:16)

1.4 在沉睡中停止线程


分为两种,另一种是先休眠后停止线程,一种是先停止线程后休眠,这两种都会抛出java.lang.InterruptedException的错误

1.4.1 先休眠后停止


自定义线程类
package com.trigl.concurrent.simplethread;

/**
 * 先休眠后停止线程
 * @author 白鑫
 * @date 2016年4月1日 上午10:33:11
 */
public class InterruptedWhenSleep extends Thread {
    @Override
    public void run() {
        super.run();
        try {
            System.out.println("run begin");
            Thread.sleep(20000);
            System.out.println("run end");
        } catch (InterruptedException e) {
            // TODO: handle exception
            System.out.println("在沉睡中被停止!进入catch!isInterrupted()=" + this.isInterrupted());
            e.printStackTrace();
        }
    }
}

测试方法
    @Test
    public void testInterruptedWhenSleep() throws InterruptedException {
        InterruptedWhenSleep thread = new InterruptedWhenSleep();
        thread.start();
        Thread.sleep(200); // 休眠在中断前面,保证thread先休眠再中断
        thread.interrupt();
    }

输出结果
run begin
在沉睡中被停止!进入catch!isInterrupted()=false
java.lang.InterruptedException: sleep interrupted
    at java.lang.Thread.sleep(Native Method)
    at com.trigl.concurrent.simplethread.InterruptedWhenSleep.run(InterruptedWhenSleep.java:14)

1.4.2 先停止后休眠


自定义线程类
package com.trigl.concurrent.simplethread;

/**
 * 先停止后休眠线程
 * @author 白鑫
 * @date 2016年4月1日 上午10:38:08
 */
public class InterruptedWhenSleep1 extends Thread {
    @Override
    public void run() {
        super.run();
        try {
            for (int i = 0; i < 100000; i++) {
                System.out.println("i=" + (i + 1));
            }
            System.out.println("run begin");
            Thread.sleep(20000);
            System.out.println("run end");
        } catch (InterruptedException e) {
            System.out.println("先停止,再遇到了sleep!进入catch!");
            e.printStackTrace();
        }
    }
}

测试方法
    @Test
    public void testInterruptedWhenSleep1() throws InterruptedException {
        InterruptedWhenSleep1 thread = new InterruptedWhenSleep1();
        thread.start();
        thread.interrupt();
        Thread.sleep(1000); // 加这个休眠是为了延迟test方法的完成,从而thread的打印报错信息
        System.out.println("end");
    }

输出结果
......
i=99999
i=100000
run begin
先停止,再遇到了sleep!进入catch!
java.lang.InterruptedException: sleep interrupted
    at java.lang.Thread.sleep(Native Method)
    at com.trigl.concurrent.simplethread.InterruptedWhenSleep1.run(InterruptedWhenSleep1.java:17)
end

1.5 暴力停止线程


可以使用Thread类的stop()方法暴力停止线程,但是这个方法是不安全的,而且是已被弃用作废的(deprecated),最好不要使用。这个例子看看就可以了,反正没人会用这个方法233333。
自定义线程类
package com.trigl.concurrent.simplethread;

/**
 * 用stop()方法暴力停止线程
 * @author 白鑫
 * @date 2016年4月1日 上午10:50:51
 */
public class StopThread extends Thread {
    private int i = 0;

    @Override
    public void run() {
        try {
            while (true) {
                i++;
                System.out.println("i=" + i);
                Thread.sleep(1000);
            }
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
}

测试方法
    @SuppressWarnings("deprecation")
    @Test
    public void testStopThread() throws InterruptedException {
        StopThread thread = new StopThread();
        thread.start();
        Thread.sleep(5000);
        thread.stop();
    }

输出结果
i=1
i=2
i=3
i=4
i=5

1.6 使用return停止线程


将方法interrupt()和return结合使用也可以停止线程。
自定义线程类
package com.trigl.concurrent.simplethread;

/**
 * 使用return停止线程
 * @author 白鑫
 * @date 2016年4月1日 下午3:21:16
 */
public class UseReturnInterrupt extends Thread {
    @Override
    public void run() {
        while (true) {
            if (this.isInterrupted()) {
                System.out.println("停止了!");
                return;
            }
            System.out.println("timer=" + System.currentTimeMillis());
        }
    }
}

测试方法
    @Test
    public void testUseReturnInterrupt() throws InterruptedException {
        UseReturnInterrupt thread = new UseReturnInterrupt();
        thread.start();
        Thread.sleep(1000);
        thread.interrupt();
        System.out.println("end");
    }

输出结果
......
timer=1459495136740
timer=1459495136740
timer=1459495136740
停止了!
end

2 线程的让步操作


线程使用yield()方法来放弃当前的CPU资源,将它让给其他任务去占用CPU执行时间。但放弃的时间不确定,有可能刚刚放弃,马上又获得CPU时间片。
上栗子~
自定义线程类
package com.trigl.concurrent.simplethread;

/**
 * 线程放弃CPU资源
 * @author 白鑫
 * @date 2016年4月1日 下午3:54:18
 */
public class YieldThread extends Thread {
    @Override
    public void run() {
        long beginTime = System.currentTimeMillis();
        int count = 0;
        for (int i = 0; i < 50000000; i++) {
            count = count + (i + 1);
//          Thread.yield(); // 主动放弃CPU资源,将这行代码注释和不注释分别跑一下,看一下区别
        }
        long endTime = System.currentTimeMillis();
        System.out.println("用时:" + (endTime - beginTime) + "毫秒!");
    }
}

测试方法
    @Test
    public void testYieldThread() throws InterruptedException {
        YieldThread thread = new YieldThread();
        thread.start();
        Thread.sleep(10000);
    }

不调用yield()方法输出结果
用时:1毫秒!

调用yield()方法输出结果
用时:4255毫秒!

可以看到,处理5千万自加1操作,调用yield()和不调用yield()方法差别还是很大的,相差了近4000倍。

3 线程的优先级


在操作系统中,线程可以划分优先级,优先级高的线程得到的CPU资源多,也就是CPU优先执行优先级较高的线程对象中的任务。
设置优先级使用setPriority()方法,得到优先级使用getPriority()方法。
在Java中,线程的优先级分为1~10这10个等级,如果小于1或者大于10,则JDK抛出IllegalArgumentException异常。
JDK中使用3个常量来预置定义优先级的值,代码如下:
  • public final static int MIN_PRIORITY = 1;
  • public final static int NORM_PRIORITY = 5;
  • public final static int MAX_PRIORITY = 10;

在Java中,线程的优先级具有继承性,比如A相称启动了B线程,则B线程的优先级与A是一样的。
上栗子:
自定义线程类
package com.trigl.concurrent.simplethread;

/**
 * 线程的优先级的继承特性
 * @author 白鑫
 * @date 2016年4月1日 下午4:48:28
 */
public class InheritPriorityThread extends Thread {
    @Override
    public void run() {
        System.out.println("InheritPriorityThread run priority=" + this.getPriority());
    }
}

测试方法
    @Test
    public void testInheritPriorityThread() {
        System.out.println("test thread begin priority=" + Thread.currentThread().getPriority());
//      Thread.currentThread().setPriority(6); // 设置当前线程的优先级
        System.out.println("test thread end priority=" + Thread.currentThread().getPriority());
        InheritPriorityThread thread = new InheritPriorityThread();
        thread.start();
    }

输出结果
test thread begin priority=5
test thread end priority=5
InheritPriorityThread run priority=5

将代码:
//      Thread.currentThread().setPriority(6); // 设置当前线程的优先级

前的注释去掉,再次运行,得到结果如下:
test thread begin priority=5
test thread end priority=6
InheritPriorityThread run priority=6

可以看到,由于在test方法中启动了另一个线程,所以他们的线程优先级相同,都是6.
OVER
......显示全文...
    点击查看全文


上一篇文章      下一篇文章      查看所有文章
2016-04-02 20:59:29  
互联网 最新文章
C++11并发API总结
16.收款(AcceptingMoney)
数据链路层综述
IP协议及IP数据报解析
《浅谈HTTP协议》
计算机网络基础
LoadRunner和RPT之间关于手动关联和参数化的
HTTPS中的对称密钥加密,公开密钥加密,数字
上班需要打卡吗?(开通微信公众号--乘着风
ofbizjmsactivemq
360图书馆 论文大全 母婴/育儿 软件开发资料 网页快照 文字转语音 购物精选 软件 美食菜谱 新闻中心 电影下载 小游戏 Chinese Culture
生肖星座解梦 人民的名义 人民的名义在线看 三沣玩客 拍拍 视频 开发 Android开发 站长 古典小说 网文精选 搜图网 天下美图
中国文化英文 多播视频 装修知识库
2017-7-21 4:46:17
多播视频美女直播
↓电视,电影,美女直播,迅雷资源↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  软件世界网 --