• java并发-线程


    前言

    近来时间比较充裕,正好又看了一遍《实战java高并发程序设计》,故而对java并发一些知识进行下总结,算是温故而知新吧。

     一,线程基础

    1,新建线程

    一般有两种实现方式实现Runnable接口或继承Thread类(Thread类本身也是实现Runnable接口)

    public class Test {
        public static void main(String[] args) throws Exception {
            Thread t1=new TestThread();
            Thread t2=new TestThread();
            Thread t3=new Thread(new TestThreadImpl());
            Thread t4=new Thread(new TestThreadImpl());
            t1.start();
            t2.start();
            t3.start();
            t4.start();
            }
    }
    class TestThread extends Thread{
        @Override
        public void run() {
            System.out.println("hello word");
        }
    }
    class TestThreadImpl implements Runnable{
        @Override
        public void run() {
            System.out.println("hello word 2");
        }
    }

    2,线程的终止

    一般来说线程在执行完毕后就会结束无须手动关闭,但凡是总有例外一下服务端的后台线程可能会常驻系统,比如它们本身就是一个无限循环,用于提供默写服务。

    Thread 提供了一个被标注为废弃的方法stop();因为stop()方法过于暴力,强行把执行一般的线程终止,这样可能会引起一些数据不一致的问题。《实战java高并发程序设计》中给出了一个的解决方案,用一个一个自定义的stop并且需要自行决定何时退出

    class ChangeObjectThread extends Thread{
        volatile boolean stopme=false;
        public void stopMe(){
            stopme=true;
        }
        @Override
        public void run() {
            while(true){
                if(stopme){
                    break;
                }
                //synchromized handle data
    
            }
        }
    }

    3,线程中断interrupt

    严格来讲,线程中断并不会让线程立即退出,而是给线程发送一个通知,告知目标线程 ,有人希望你退出了。至于目标线程街道通知后如何处理,则完全有线程自行决定,如果无条件退出那么又遇到和stop()相同的问题了。

    public void interrupt() //中断线程
    public boolean isInterrupted()//判断是否被中断
    public static boolean interrupted()//判断是否被中断,并清除当前中断状态
    public class Test {
        public static Object o = new Object();
    
        public static void main(String[] args) throws Exception {
            Thread t1 = new TestThread();
            t1.start();
            Thread.sleep(1000);
            t1.interrupt();
        }
    }
    
    class TestThread extends Thread {
        @Override
        public void run() {
            int i=0;
            while (!isInterrupted()) {
                i++;
                System.out.println(Thread.currentThread().getName()+" ("+this.getState()+") loop " + i);  
            }
        }
    }

    另:当线程由于被调用了sleep(), wait(), join()等方法而进入阻塞状态;若此时调用线程的interrupt()将线程的中断标记设为true。由于处于阻塞状态,中断标记会被清除,同时产生一个InterruptedException异常,这时就要用合适的方式处理InterruptedException了

    4,Object 等待(wait)和通知(notify)

      这两个方法是由Object类提供的,并不是在Thread中的。当一个对象实例调用了wait()方法后,当前线程就会在这个对象上等待。如:线程A中调用了obj.wait()方法,那么线程A就会停止继续执行,而转为等待状态,直到调用了obj.notify()方法为止。

    wait(),notify()方法的调用鼻血包含在对应的synchronized语句中,也就是要先获得目标对象锁资源。调用了wait后,会释放锁资源。

    public class Test {
        public static Object o = new Object();
    
        public static void main(String[] args) throws Exception {
            Thread t1 = new TestThread();
            Thread t2 = new TestThread();
            Thread t3 = new TestThread();
            Thread t4 = new TestThreadNotify();
            t1.start();
            t2.start();
            t3.start();
            t4.start();
        }
    
    }
    
    class TestThread extends Thread {
        @Override
        public void run() {
            synchronized (Test.o) {
                try {
                    System.out.println(Thread.currentThread().getName()+"waiting....");
                    Test.o.wait();
                    System.out.println(Thread.currentThread().getName()+"start....");
                    Thread.sleep(2000);
                } catch (Exception e) {
                    e.printStackTrace();
                }
                System.out.println(Thread.currentThread().getName()+"stop....");
            }
        }
    }
    
    class TestThreadNotify extends Thread {
        @Override
        public void run() {
            synchronized (Test.o) {
                System.out.println("TestThreadNotify start....");
                try {
                    Test.o.notifyAll();
                } catch (Exception e) {
                    e.printStackTrace();
                }
                System.out.println("TestThreadNotify stop....");
            }
        }
    }
    }
    Thread-0waiting....
    TestThreadNotify start....
    TestThreadNotify stop....
    Thread-2waiting....
    Thread-1waiting....
    Thread-0start....
    Thread-0stop....

    5,等待线程结束(join)和谦让(yield)


    很多时候,一个线程的输入可能非常依赖于另外一个或者多个线程的输出,此时,这个线程就需要等待依赖线程执行完毕,才能继续执行。JDK 提供了join()操作来实现这个功能,如下所示,显示了2个join()方法:

    public final void join() throws InterruptedException
    
    public final synchronized void join(long millis) throws InterruptedException

    第一个join()方法表示无限等待,它会一直阻塞当前线程,直到目标线程执行完毕。

    第二个方法给出了一个最大等待时间,如果超过给定时间目标线程还在执行,当前线程也会因为“等不及了”,而继续往下执行。

    join()的本质是让调用线程wait()在当前线程对象实例上;

    public class Test {
        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);
    
        }
    
    }

    主函数中,如果不使用join()等待AddThread ,那么得到的i 很可能是0或者一个非常小的数字。因为AddThread 还没开始执行,i 的值就已经被输出了。但在使用join()方法后,表示主线程愿意等待AddThread 执行完毕,跟着AddThread 一起往前走,故在join()返回时,AddThread 已经执行完成,故i 总是10000000

    yiead()

    这是一个静态方法,一旦执行,它会使当前线程让出CPU 。但要注意,让出CPU 并不表示当前线程不执行了。当前线程在让出CPU 后,还会进行CPU 资源的争夺,但是是否能够再次被分配到,就不一定了

    待续

  • 相关阅读:
    数据结构矩阵问题总结
    数据结构:二维ST表
    mysql--时区表问题(Windows环境下)
    mysql--基本命令
    Django2.0--创建缓存表
    git--基本命令
    阿里云主机--重置系统后的登录问题
    链表中倒数第K个结点
    从尾到头打印链表
    替换空格
  • 原文地址:https://www.cnblogs.com/china2k/p/8001371.html
Copyright © 2020-2023  润新知