多线程笔记:多线程基础 - 2

线程的暂停和恢复:即让线程暂时停止运行,并能恢复
    suspend()  暂停线程。为已经过时方法
    resume()   恢复暂停的线程。为已经过时的方法
    
    例子
        public class SuspendThread extends Thread{
            private int i;
            public int getI() {
                return i;
            }
            public void setI(int i) {
                this.i = i;
            }

            @Override
            public void run() {
                super.run();
                while (true) {
                    i++;
                }
            }
        }
        
        SuspendThread thread = new SuspendThread();
        thread.start();
        Thread.sleep(1000);
        System.out.println(thread.getI());
        Thread.sleep(1000);
        thread.suspend();        //线程暂停
        System.out.println(thread.getI());
        Thread.sleep(1000);
        System.out.println(thread.getI());
        thread.resume();        //线程恢复
        thread.sleep(1000);
        System.out.println(thread.getI());
        
        运行结果:
            502839629
            1079189339
            1079189339        //线程暂停到恢复期间线程停止执行,i值不变
            1721670999

    这两个方法的缺点:
        如果使用不当,极易造成公共的同步对象的独占,使得其他线程无法访问公共同步对象
        
        如某个线程在同步的代码中暂停了,而没有恢复,则同步锁被永远占用。
        
        这两个方法本身是不同步的,易造成数据不同步的情况
        
        如:
            public class SuspendThread extends Thread{

                private int i;

                private int j;

                public void setValue(int i, int j){
                    this.i = i;
                    Thread.currentThread().suspend();    //线程启动后设置了i值后暂停,由于不同步,此时这个对象被其他线程访问则出现数据不一致问题
                    this.j = j;
                };
                

                @Override
                public void run() {
                    setValue(122, 333);
                }
            }
        
        
            SuspendThread thread = new SuspendThread();
            thread.start();
            Thread.sleep(100);
            System.out.println(thread.getI() + "  " + thread.getJ());   //主线程获取到了子线程修改的成员变量
        
            运行结果 : 122  0
                
yield()方法,为Thread的静态方法,作用是放弃当前cpu资源,将它让给其他任务去执行,当放弃的时间不确定。 可能刚放弃马上又获得cpu时间片
    
    public class YieldThread extends Thread{

    private int i;

    @Override
    public void run() {
            long begin = System.currentTimeMillis();
            for (int k = 0; k < 50000000; k++) {
                i += k;
            }
            long end = System.currentTimeMillis();
            System.out.println("不执行Thread.yield();时执行时间为:" + (end - begin) + "毫秒");

            long begin2 = System.currentTimeMillis();
            for (int k = 0; k < 50000000; k++) {
                Thread.yield();        //没次循环调用此方法
                i += k;
            }
            long end2 = System.currentTimeMillis();
            System.out.println("执行Thread.yield();时执行时间为:" + (end2 - begin2) + "毫秒");
        }
    }    
        
    
    YieldThread thread = new YieldThread();
    thread.start();

    执行结果:
        不执行Thread.yield();时执行时间为:16毫秒
        执行Thread.yield();时执行时间为:24541毫秒        
        
线程优先级:
    在操作系统中,线程可以划分优先级,优先级较高的线程得到的cpu资源较多,cpu有限执行优先级较高的线程对象中的任务
    
    1.设置线程优先级的方法:
        setPriority();
        
    2.优先级分为1-10 这10个等级,小于1或大于10将抛出 IllegalArgumentException异常
        YieldThread thread1 = new YieldThread();
        thread1.setName("优先级10的线程");
        thread1.setPriority(10);
        thread1.start();

        YieldThread thread2 = new YieldThread();
        thread2.setName("优先级1的线程");
        thread2.setPriority(1);
        thread2.start();
        
        运行结果:    
            优先级10的线程的线程执行时间为:171毫秒        //优先级高的执行快  //注意这里执行快不是因为这个线程先被main启动,与调用顺序无关
            优先级1的线程的线程执行时间为:296毫秒        

        
    3.线程的优先级具有继承性:即A线程启动了B线程,则B线程的优先级和A相同
        
        如:    
            System.out.println("main线程优先级:" + Thread.currentThread().getPriority());
            YieldThread thread = new YieldThread();
            thread.start();        //主线程启动thread线程
            System.out.println(thread.getName() + "线程优先级:" + thread.getPriority());
            
            运行结果:    
                main线程优先级:5
                Thread-0线程优先级:5    //继承了main线程的优先级
        
    4.优先级具有随机性:
        不能说优先级高就一定执行的更快,具有随机性,即大部分情况下优先级高的执行的快,是个概率问题
            
守护线程:
    java线程分为两种:用户线程和守护线程
        守护线程是一种特殊的线程:又陪伴的含义,守护线程是为其他线程的运行提供便利服务的。
        jvm示例中只要有非守护线程没有结束,守护线程就不会结束。只有当所有的非守护线程结束时,守护线程才会结束销毁
        
        典型的守护线程:GC(垃圾回收器)
        
        
    例子:
        public class DaemonThread extends Thread{
            private int i;

            @Override
            public void run() {
                while (true) {
                    try {
                        System.out.println(i++);
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
                        
        public static void main(String[] args) {
            try {
                DaemonThread daemonThread = new DaemonThread();
                daemonThread.setDaemon(true);    //设置线程为守护线程
                daemonThread.start();
                Thread.sleep(5000);
                System.out.println("main主线程要结束了。守护线程将不再打印了,也会结束");

            } catch (Exception e) {
                e.printStackTrace();
            }
        }        
                
        运行结果:    
            0
            1
            2
            3
            4
            main主线程要结束了。守护线程将不再打印了,也会结束    //主线程结束后,守护线程跟着结束
                
                
                
                
                
                
                
                

 

posted @ 2019-07-13 10:29  foreast  阅读(112)  评论(0编辑  收藏  举报