zoukankan      html  css  js  c++  java
  • 多线程开发之基本线程机制

    Thread.yield():

    对静态方法 Thread.yield() 的调用声明了当前线程已经完成了生命周期中最重要的部分,可以切换给其它线程来执行。该方法只是对线程调度器的一个建议,而且也只是建议具有相同优先级的其它线程可以运行。

    /**
     * Thread.yield()
     * */
    
    public class test1 implements Runnable{
        private int index;
        private int id;
        test1(int index){
            id = index;
        }
        @Override
        public void run() {
            while(true){
                System.out.println("线程"+id+"执行中");
                Thread.yield();
            }
        }
    
        public static void main(String[] args) {
            for (int i = 0; i < 10; i++) {
                new Thread(new test1(i)).start();
            }
        }
    }

    Executor:

    CachedThreadPool:为每个任务都创建一个线程
    FixedThreadPool:限制线程的数量,每次需要线程的事件处理器,通过直接从线程池中获取线程,使用完将线程放回线程池,多有线程都会一致存于线程池,知道显示的执行shutdown()方法
    SingleThreadExecutor:可以将其看成大小为1的FixedThreadPool
    CachedThreadPool:
    /**
     * Executor
     * CachedThreadPool:为每个任务都创建一个线程
     * */
    public class test2 implements Runnable{
        private int id;
        test2(int id){
            this.id = id;
        }
        @Override
        public void run() {
            System.out.println("线程"+id);
        }
    
        public static void main(String[] args) {
            ExecutorService exec = Executors.newCachedThreadPool();
            for (int i = 0; i < 3; i++) {
                exec.execute(new test2(i));
            }
            exec.shutdown();
        }
    }
    FixedThreadPool:
    /**
     * Executor
     * FixedThreadPool:所有任务只能使用固定大小的线程;
     * */
    public class test3 implements Runnable{
        private int id;
        test3(int id){
            this.id = id;
        }
        @Override
        public void run() {
            System.out.println("线程"+id);
        }
    
        public static void main(String[] args) {
            ExecutorService exec = Executors.newFixedThreadPool(3);
            for (int i = 0; i < 3; i++) {
                exec.execute(new test3(i));
            }
            exec.shutdown();
        }
    }

    SingleThreadExecutor:

    /**
     * Executor
     * FixedThreadPool:所有任务只能使用固定大小的线程;
     * */
    
    public class test4 implements Runnable{
        @Override
        public void run() {
            System.out.println("线程执行");
        }
    
        public static void main(String[] args) {
            ExecutorService exec = Executors.newSingleThreadExecutor();
            exec.execute(new test4());
            exec.shutdown();
        }
    }

    三种方式的选择

    CachedThreadPool在程序执行过程中通常会创建与所需数量相同的线程,然后在它回收旧线程时停止创建新线程,因此它是合理的Executor的首选。只有当这种方式会引发问题时,我们才需要考虑切换到FixedThreadPool。

    sleep()

    Thread.sleep(millisec) 方法会休眠当前正在执行的线程,millisec 单位为毫秒。

    sleep() 可能会抛出 InterruptedException,因为异常不能跨线程传播回 main() 中,因此必须在本地进行处理。线程中抛出的其它异常也同样需要在本地进行处理。

    sleep()调用的时候回阻塞当前进程执行其他进程,可用 Interrupted()中断当前进程,进程阻塞的时候不会释放锁。

    /**
     * sleep()
     * */
    
    public class SleepTest implements Runnable{
        private int id;
        SleepTest(int id){
            this.id = id;
        }
    
        @Override
        public void run() {
            System.out.println("线程"+id+"before");
            try {
                Thread.sleep(1);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("线程"+id+"after");
        }
    
        public static void main(String[] args) {
            ExecutorService exec = Executors.newCachedThreadPool();
            for (int i = 1; i <= 5; i++) {
                exec.execute(new SleepTest(i));
            }
            exec.shutdown();
        }
    }

    优先级

    可以在任意时刻使用setPriority()设置优先级,使用getPriority()读取现用线程的优先级

    /**
     * priority
     * */
    public class PriorityTest implements Runnable{
        private int priority;
        private int id;
        public PriorityTest(int id,int priority){
            this.priority = priority;
            this.id = id;
        }
    
        @Override
        public void run() {
            Thread.currentThread().setPriority(priority);
            System.out.println("线程"+id+"running");
        }
    
        public static void main(String[] args) {
            ExecutorService exec = Executors.newCachedThreadPool();
            for (int i = 1; i <= 3; i++) {
                exec.execute(new PriorityTest(i,Thread.MIN_PRIORITY));
            }
            exec.execute(new PriorityTest(4,Thread.MAX_PRIORITY));//我们会发现线程4会比线程123先执行
            exec.shutdown();
        }
    }

    后台线程 Daemon:

    守护线程(后台线程)是程序运行时在后台提供服务的线程,不属于程序中不可或缺的部分。

    当所有非守护线程结束时,程序也就终止,同时会杀死所有守护线程。

    main() 属于非守护线程。

    使用 setDaemon() 方法将一个线程设置为守护线程

    /**
     * Daemon
     * */
    public class Daemon implements Runnable{
        private int id;
        public Daemon(int id){
            this.id = id;
        }
    
        @Override
        public void run() {
            System.out.println("线程"+id+"running");
            try {
                Thread.sleep(1);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    
        public static void main(String[] args) throws InterruptedException {
            for (int i = 0; i < 20; i++) {
                Thread daemon = new Thread(new Daemon(i));
                daemon.setDaemon(true);
                daemon.start();
            }
            /*20条线程并没有都运行完毕*/
            TimeUnit.MILLISECONDS.sleep(1);//不加这条堵会儿主线程,主线程结束后所有后台线程都被结束,一条后台线程的输出结果都看不到
        }
    }

    共同学习共同成长,若有错误,欢迎指出

  • 相关阅读:
    第二节:Java环境变量配置
    第一节:VS充当IIS的配置步骤(VS2017和VS2019)
    .Net进阶系列(21)-跨域请求
    02-Unity深入浅出(二)
    第十五节:Expression表达式目录树(与委托的区别、自行拼接、总结几类实例间的拷贝)
    01-Unity深入浅出(一)
    第十二节:SQLServer存储过程详解及EFCore调用
    Android 组件系列-----Activity的传值和回传值
    Access大数据高效分页语句
    C#清除HTML样式
  • 原文地址:https://www.cnblogs.com/czsy/p/10531560.html
Copyright © 2011-2022 走看看