zoukankan      html  css  js  c++  java
  • Java多线程——<八>多线程其他概念

    一、概述

      到第八节,就把多线程基本的概念都说完了。把前面的所有文章加连接在此:

      Java多线程——<一>概述、定义任务

      Java多线程——<二>将任务交给线程,线程声明及启动

      Java多线程——<三>简单的线程执行:Executor

      Java多线程——<四>让线程有返回值

      Java多线程——<五>后台线程(daemon)

      Java多线程——<六>更方便的线程

      Java多线程——<七>多线程的异常捕捉

      均是个人理解和总结,代码均来自《thinking in java》,有问题欢迎大家指正。

    二、多线程的其他概念

      1.休眠

      休眠,其实就是让线程暂停一段时间,也就是阻塞一段时间。例如:每个打印之后,每个线程都要睡眠(即阻塞),这使得线程调度器可以切换到另一个线程,进而驱动另一个任务。这导致了线程在执行顺序上得到了保证,可以通过查看打印输出消息证实这一点。

    public class TaskSleepingTask extends Task{
        @Override
        public void run() {
            try{
                while(countDown-- > 0){
                    System.out.println(status());
                    /*
                     * 每个打印之后,每个线程都要睡眠(即阻塞),这使得线程调度器可以切换到另一个线程,进而驱动另一个任务
                     */
                    TimeUnit.MICROSECONDS.sleep(100000);
                }    
            /*
             * 因为异常不能跨线程传回给main,所以你必须在线程里处理该异常
             */
            }catch(InterruptedException e){
                System.out.println();
            }
        }
        public static void main(String[] args){
            ExecutorService exec = Executors.newCachedThreadPool();
            for(int i = 0 ; i < 5 ; i++){
                exec.execute(new TaskSleepingTask());
            }
            exec.shutdown();
        }
    }

      但是,这不代表你就可以通过休眠的方式来保证任务的执行顺序(顺序行为依赖于底层的线程机制,这种机制在不同的操作系统之间是有差异的

      要想控制顺序的解决办法:1、同步控制,2、协作线程(以后再做序数)

      2.优先级

      优先级代表了该线程的重要性,线程调度器将倾向于让优先级高的线程先执行(但这不意味着优先权较低的线程将得不到执行,即优先权不会导致死锁)。优先级较低的线程仅仅是执行频率较低,在绝大多数时间里,所有线程都应该以默认优先级运行,试图操纵线程优先级通常是一种错误。

      通过Thread.currentThread()方法来获得对驱动该任务的Thread对象的引用,然后设置线程优先级。

    public class TaskPriority implements Runnable{
        private int countDown = 5;
        /*
         * 变量d用来确保不进行任何编译器优化
         */
        @SuppressWarnings("unused")
        private volatile double d;//no optimization
        private int priority;
        public TaskPriority(int priority){
            this.priority = priority;
        }
        /*
         * 打印线程的名称、线程的优先级以及线程所属的“线程组”
         *在线程内部,通过调用Thread.currentThread()来获得对驱动该任务的Thread对象的引用
         */
        public String toString(){
            return Thread.currentThread()+":"+countDown;
        }
        @Override
        public void run() {
            /*
             * 优先级应该在run的开头部分设定,在构造器中设置他们不会有任何好处,因为Executor在此刻还没有开始执行任务
             */
            Thread.currentThread().setPriority(priority);
            /*
             * 执行了10000次浮点运算,数学 运算是可以中断的,这里运算时间足够长,
             * 因此线程调度机制才来得及介入,交换任务并关注优先级,使得最高优先级的线程被优先选择
             */
            while(true){
                for(int i = 1 ;i < 10000;i++){
                    d+=(Math.PI + Math.E)/(double)i;
                    if(i%1000==0)
                        Thread.yield();
                    System.out.println(this);
                    if(--countDown == 0 ) 
                        return;
                }
            }
        }
        public static void main(String[] args){
            ExecutorService exec = Executors.newCachedThreadPool();
            for(int i = 0 ; i < 5;i++){
                exec.execute(new TaskPriority(Thread.MIN_PRIORITY));//1
            }
            exec.execute(new TaskPriority(Thread.MAX_PRIORITY));//10
            exec.shutdown();
        }
    }

      尽管jdk有10个优先级,但是它与多数操作系统都不能映射得很好(windows7个,solaris2个),唯一可移植的方法是当调整优先级的时候,只试用MAX_PRIORITY/NORM_PRIORITY/MIN_PRIORITY三种声明

      3.让步

      在你已经确认完成了在run方法的循环的一次迭代过程中所需的工作,就可以给线程调度机制一个暗示:你的工作已经做的差不多了,可以让别的线程试用cpu了。(让相同优先级的其他线程可以运行)。

      java提供了调用yield()方法来实现。过这只是暗示没有任何机制保证它会被采纳,所以不能依赖该方法。如上例。

     

  • 相关阅读:
    使用 cordova-plugin-wechat 分享返回后闪退解决方法
    恢复删除的表
    移动端还原设计图
    js文本差异比较
    windows使用nvm安装nodejs后升级npm报错
    windows添加右键菜单"在此处打开cmd窗口"
    cordova热更新
    js变量提升
    c# 判断字符串是否是日期格式需要注意的一点小问题
    剑指offer_和为S的两个数字
  • 原文地址:https://www.cnblogs.com/brolanda/p/4726668.html
Copyright © 2011-2022 走看看