美文网首页
《实战Java高并发程序设计》学习记录2

《实战Java高并发程序设计》学习记录2

作者: 少寨主的互联网洞察 | 来源:发表于2018-11-09 15:21 被阅读0次

    什么是线程

    线程是进程内的执行单元

    线程的基本操作

    image.png

    新建线程

    image.png

    为什么呢?看看源码


    image.png
    image.png
    image.png

    停止线程

    Thread.stop() 不推荐使用。它会释放所有monitor
    示例:


    image.png

    线程中断(怎么优雅的让一个线程停止运作)

    示例1:如果仅仅是下面这样的方式

    image.png

    线程并不会终止,虽然已经通知它中断运行了,但是没有作相应的判断标志位,所以线程并不会去理会这个中断通知

    示例2:(优雅的方式)

    image.png
    补充
    public void Thread.interrupt() // 中断线程
    public boolean Thread.isInterrupted() // 判断是否被中断
    public static boolean Thread.interrupted() // 判断是否被中断,并清除当前中断状态
    

    示例三

    image.png

    挂起( suspend)和继续执行( resume)线程

    – suspend()不会释放锁
    – 如果加锁发生在resume()之前 ,则死锁发生

    image.png
    • 为什么?看看源码
    @Deprecated
        public final void suspend() {
            checkAccess();
            suspend0();
        }
    

    解释怎么说?

    @deprecated This method has been deprecated, as it is
    * inherently deadlock-prone. If the target thread holds a lock on the
    * monitor protecting a critical system resource when it is suspended, no
    * thread can access this resource until the target thread is resumed. If
    * the thread that would resume the target thread attempts to lock this
    * monitor prior to calling <code>resume</code>, deadlock results. Such
    * deadlocks typically manifest themselves as "frozen" processes.

    代码实现

    package someTest;
    
    public class BadSuspend {
        public static Object u=new Object();
        static ChangeObjectThread t1=new ChangeObjectThread("t1");
        static ChangeObjectThread t2=new ChangeObjectThread("t2");
        
        public static class ChangeObjectThread extends Thread{
            public ChangeObjectThread(String name) {
                super.setName(name);
            }
            @Override
            public void run() {
                synchronized (u) {
                    System.out.println("in "+getName());
                    Thread.currentThread().suspend();
                }
            }
        }
        public static void main(String[] args) throws InterruptedException {
            t1.start();
            Thread.sleep(100);
            t2.start();
            t1.resume();
            t2.resume();
            t1.join();
            t2.join();
        }
    }
    
    

    上面这个程序就会卡在主程序里面出不来,因为t2的resume()方法先执行,suspend()方法后执行,导致t2一直卡在suspend挂起状态出不来,所以就卡住了。

    等待线程结束( join)和谦让(yeild)

    • yield:我把cpu让出来,大家一起竞争,给大家一个竞争的机会,当然自己还是有可能再次获得cpu的执行权
    • join:
    public class JoinMain {
    public volatile static int i=0;
    public static class AddThread extends Thread{
    @Override
    public void run() {
    for(i=0;i<10000000;i++);
    }
    }
    public static void main(String[] args) throws InterruptedException {
    AddThread at=new AddThread();
    at.start();
    at.join();
    System.out.println(i);
    }
    }
    

    上面示例表示主线程在at.join();等待at这个线程先执行完,再往下走
    join的本质:让所有等待当前线程的其他线程等待

    join的本质
    while (isAlive()) {
    wait(0);
    }
    
    image.png

    当然,等待的时间也是可以设置的,比如我想等待一段时间以后就不等了^^
    建议:


    image.png

    源码里面直接说明,建议不要使用Thread对象实例的wait和notify方法,因为这些方法操作系统会进行调用,你调用了不保证达到理想的效果

    守护线程

    • 在后台默默地完成一些系统性的服务,比如垃圾回收线程、 JIT线程就可以理解为守护线程
    • 当一个Java应用内,只有守护线程时, Java虚拟机就会自然退出
    package someTest;
    
    public class DaemonDemo {
        public static class DaemonT extends Thread{
            public void run() {
                while(true) {
                    System.out.println("I am alive");
                    try {
                        Thread.sleep(1000);
                    }catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
        public static void main(String[] args) {
            Thread t=new DaemonT();
            t.setDaemon(true);
            t.start();
            
        }
    }
    
    

    上面这个程序运行起来后,啪--就停了,因为它被设置为了守护线程,满足上面的第二条性质

    线程优先级

    public final static int MIN_PRIORITY = 1;
    public final static int NORM_PRIORITY = 5;
    public final static int MAX_PRIORITY = 10;
    
    image.png
    • 高优先级的线程更容易再竞争中获胜,概率问题,结果不保证

    线程同步操作

    • synchronized

    – 指定加锁对象:对给定对象加锁,进入同步代码前要获得给定对象的锁。
    – 直接作用于实例方法:相当于对当前实例加锁,进入同步代码前要获得当前实例的锁。
    – 直接作用于静态方法:相当于对当前类加锁,进入同步代码前要获得当前类的锁。

    package someTest;
    
    public class AccountingAsync implements Runnable{
        static AccountingAsync instance=new AccountingAsync();
        static int i=0;
        @Override
        public void run() {
            for(int j=0;j<10000;j++) {
                synchronized(instance) {
                    i++;
                }
                
            }
        }
        public static void main(String[] args) throws InterruptedException {
            Thread t1=new Thread(instance);
            Thread t2=new Thread(instance);
            t1.start();
            t2.start();
            t1.join();
            t2.join();
            System.out.println(i);
        }
    }
    
    

    以上正确输出20000
    根据synchronized修饰的位置不同,有不同的作用域,所以在使用锁的时候一定要注意用到合适的对象上,比如将这个关键字用在静态方法上,就相当于对类进行加锁,结果还是20000

    package someTest;
    
    public class AccountingAsync implements Runnable{
        static AccountingAsync instance=new AccountingAsync();
        static int i=0;
        public static synchronized void increase() {
            i++;
        }
        @Override
        public void run() {
            for(int j=0;j<10000;j++) {
                increase();
            }
        }
        public static void main(String[] args) throws InterruptedException {
            Thread t1=new Thread(instance);
            Thread t2=new Thread(instance);
            t1.start();
            t2.start();
            t1.join();
            t2.join();
            System.out.println(i);
        }
    }
    
    

    Object.wait() Obejct.notify()

    Object.wait():使线程等待在当前对象上
    Obejct.notify():通知等待在当前对象上的线程

    • 注意事项:以上两个方法必须要在拿到对象监视器锁以后才能调用,没拿到以前是不能调用的,同时如果一个线程拿到了对象监视器锁,然后调用wait()方法就会释放当前对象的监视器锁,而notify方法不一样,不会立即释放,而是等它执行完了再释放

    相关文章

      网友评论

          本文标题:《实战Java高并发程序设计》学习记录2

          本文链接:https://www.haomeiwen.com/subject/juonxqtx.html