• 多线程学习(四)


    让步

    yield() 给线程调度机制一个暗示:你的工作已经做得差不多了,可以让别的线程使用cpu了.这只是一个暗示,没有任何机制保证它会被采纳。

    后台线程

    后台线程是指程序执行时候,在后台提供一种通用服务的线程。并且这种线程并不属于程序的不可缺少的一部分。因此当所有的非后台线程结束时,程序也就截止了,同时也会杀死进程中所有后台线程。例如 main()就是一个非后台线程

    package thread.test1;
    
    import java.util.concurrent.TimeUnit;
    
    public class SimpleDaemons implements Runnable {
    
    	@Override
    	public String toString() {
    		return Thread.currentThread().getName();
    	}
    
    	@Override
    	public void run() {
    		// TODO Auto-generated method stub
    		while (true) {
    			try {
    				TimeUnit.MILLISECONDS.sleep(100);
    			} catch (InterruptedException e) {
    				// TODO Auto-generated catch block
    				e.printStackTrace();
    			}
    			System.out.println(this);
    		}
    	}
    
    	public static void main(String[] args) throws InterruptedException {
    		for(int i=0;i<10;i++){
    			Thread t=new Thread(new SimpleDaemons());
    			t.setDaemon(true);
    			t.start();
    		}
    		System.out.println("all daemons started!");
    		TimeUnit.MILLISECONDS.sleep(1200);
    		System.out.println("main over");
    	}
    }
    
    all daemons started!
    Thread-6
    Thread-3
    Thread-8
    Thread-9
    Thread-0
    Thread-5
    Thread-4
    ....
    Thread-6
    Thread-2
    main over
    Thread-1
    Thread-5
    Thread-9
    

    这里是显示的设置线程为后台线程,当然也可以通过定制ThreadFactory定制由Executor创建的线程的属性(这句话拗口)代码如下:
    定制的ThreadFactory:

    public class DaemonThreadFactory implements ThreadFactory {
    
    	@Override
    	public Thread newThread(Runnable r) {
    		// TODO Auto-generated method stub
    		Thread t=new Thread(r);
    		t.setDaemon(true);
    		return t;
    	}
    
    }
    
    public class DaemonFromFactory implements Runnable {
    	
    	@Override
    	public String toString() {
    		// TODO Auto-generated method stub
    		return super.toString();
    	}
    
    	@Override
    	public void run() {
    		// TODO Auto-generated method stub
    		
    		while(true){
    			try {
    				TimeUnit.MILLISECONDS.sleep(100);
    			} catch (InterruptedException e) {
    				// TODO Auto-generated catch block
    				e.printStackTrace();
    			}
    			System.out.println(this);
    		}
    	}
    	public static void main(String[] args) throws Exception {
    		ExecutorService exec=Executors.newCachedThreadPool(new DaemonThreadFactory()); //通过ThreadFactory 定制ExecutorService
    		for(int i=0;i<5;i++){
    			exec.execute(new DaemonFromFactory());
    		}
    		System.out.println("all daemon run!");
    		TimeUnit.MILLISECONDS.sleep(1200);
    	}
    
    }
    

    也可通过继承ThreadPoolExecutor加定制ThreadFactory 来定制exector来设置线程的属性:

    public class DaemonThreadPoolExecutor extends ThreadPoolExecutor {
    
    	public DaemonThreadPoolExecutor() {
    		super(0, Integer.MAX_VALUE, 60L, TimeUnit.SECONDS, new SynchronousQueue<Runnable>(), new DaemonThreadFactory());//其实这里参数除了ThreadFactory 都是CachedThreadPool的参数配置
    		/**
    		 * 构造方法中各个参数的意义: 
    		 * corePoolSize: 线程池维护线程的最少数量
    		 * 
    		 * maximumPoolSize:线程池维护线程的最大数量
    		 * 
    		 * keepAliveTime: 线程池维护线程所允许的空闲时间
    		 * 
    		 * unit: 线程池维护线程所允许的空闲时间的单位
    		 * 
    		 * workQueue: 线程池所使用的缓冲队列
    		 * 
    		 * handler: 线程池对拒绝任务的处理策略
    		 */
    	}
    
    	public static void main(String[] args) throws Exception {
    		ExecutorService exec = new DaemonThreadPoolExecutor();
    		for (int i = 0; i < 5; i++) {
    			exec.execute(new DaemonFromFactory());
    		}
    		System.out.println("all daemon run");
    		TimeUnit.MILLISECONDS.sleep(1200);
    	}
    }
    

    ThreadPoolExecutor 介绍:http://blog.csdn.net/wangwenhui11/article/details/6760474
    SynchronousQueue 介绍:http://ifeve.com/java-synchronousqueue/

    可以通过isDaemon() 来判断一个线程是否是后台线程,一个后台线程创建的线程也是后台线程。
    后台线程可以在不执行finally的情况下就终止其线程

    public class ADaemon implements Runnable {
    
    	@Override
    	public void run() {
    		// TODO Auto-generated method stub
    		try {
    			System.out.println("a daemon is runing");
    			TimeUnit.MILLISECONDS.sleep(1000);
    		} catch (InterruptedException e) {
    			// TODO Auto-generated catch block
    			e.printStackTrace();
    		}finally {
    			System.out.println("finally block exec?");
    		}
    	}
    	public static void main(String[] args) throws Exception {
    		Thread t=new Thread(new ADaemon());
    		t.setDaemon(true);
    		t.start();
    	}
    }
    //output
    //a daemon is runing  有可能在后台线程还没有运行起来主线程就结束了,所以可能什么都不输出,多运行几次能看到这个输出结果
    

    因此不能优雅的关闭后台线程,后台线程结束也没有任何确认形式

  • 相关阅读:
    剑指 Offer 22. 链表中倒数第k个节点
    剑指 Offer 21. 调整数组顺序使奇数位于偶数前面
    Leetcode1450. 在既定时间做作业的学生人数
    Leetcode1572. 矩阵对角线元素的和
    Leetcode 1480. 一维数组的动态和
    Idea连接数据库报错
    Java实现二叉树层次遍历并存入List的方法:从上往下,从左往右
    SpringCloud资源网站
    Java循环对list进行remove
    Java中字符串判空的正确打开方式
  • 原文地址:https://www.cnblogs.com/joeCqupt/p/6814665.html
Copyright © 2020-2023  润新知