多线程中止线程的方法

public class Test{

    private static class UseThread extends Thread {
        public UseThread(String name) {
            super(name);
        }
        @Override
        public void run() {
            //如果现在这个while的条件不是“!isInterrupted()”而是“true”,那么即使main方法里调用了test.interrupt()还是无法终止线程的,这就是java协作式。
            while (!isInterrupted()) {
                System.out.println("Thread " + Thread.currentThread().getName() + " is running.");
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                    interrupt();//当线程调用了wait(),join(),sleep()方法时,方法会抛出InterruptedException,这个时候线程的中断标志会被复位成为false,所以这个时候我们应该在catch里面再调用一次interrupt(),再次中断一次。
                }
            }
        }
    }

    public static void main(String[] args) throws ExecutionException, InterruptedException {
        UseThread test = new UseThread("myThread");
        test.start();
        //让main线程等待
        Thread.sleep(500);
        test.interrupt();

    }
}
  1. interrupt():是属于Thread类的方法,作用终止一个线程,但并不是强行关闭一个线程(java的线程是协作式的,不是强迫式的,调用一个线程的interrupt()方法并不会强制关闭一个线程,它就好比其他线程对要关闭的线程打了一声招呼,告诉被关闭线程它要中断了,但被关闭线程什么时候关闭完全由它自身做主),线程调用该方法并不会立刻终止。既然调用interrupt()方法起不到终止线程的目的,那么它为什么要这样设计?这样设计时为了让每个线程有充分的时间去做线程的清理工作。进行开发的时候要对线程的中断请求进行处理,否则就不是一个设计良好的并发程序。总的来说,它的目的只是把线程中的“中断标志位”置为true

  2. isInterrupted(),判定当前线程是否处于中断状态。通过这个方法判断中断标志位是否为true。

  3. static方法isInterrupted(), 也是判断当前线程是否处于中断状态。当调用此方法时,它会把中断标志位改为false。
    另外,有的人喜欢在类里定义一个boolean的标志来中断线程。这种方式一般情况下能工作,但有些情况又不能工作、譬如在线程内调用了一个阻塞的方法(sleep\wait…),那么线程会一直阻塞在那个地方,这个时候即使你改变了自己定义的标志,它也不会去判断while的条件的,一定要线程从阻塞中被唤醒、并且执行完阻塞后的代码后才会回到while的判断,这就造成了线程在处理响应时非常不及时。

  4. volatile是最轻量级的保证同步的方法,但它一般只使用于一个线程写,多个线程读这种场景。

  5. run()和start()的区别:调用run方法其实就像普通的类调用类中的方法一样,run()方法由谁调用就归宿与哪个线程。只有调用start()方法才是真正的启动线程。
    多线程中止线程的方法_第1张图片

  6. 就绪状态也成为可运行状态,调用了一个线程的start()方法,形成就处于可运行状态,但这个时候并不是运行状态,只有当cpu调度到该线程才是运行状态。

  7. yield()方法的作用是,当一个线程运行完了,就把cpu的时间让出来。那么它与sleep()方法的区别呢?调用sleep()方法,在sleep()的时间段内,cpu是不会再调度该线程,但是调用了yield()方法的下一时刻,cpu还是有可能会调度到该线程的

线程的共享

synchronized(内置锁),要么加载方法上面,要么是用作同步块的形式来使用,最大的作用是确保在多个线程在同一时刻只能有一个线程处于方法或同步块之中,这样它就保证了线程对变量访问的可见性与排差性。 锁的是对象,不是代码块,每个对象在内存的对象头上有一个标志位,标志位上有1~2个字节标志它为一个锁,synchronized的作用就是当所有的线程去抢这个对象的标志位,谁把这个标志位指向了自己,那就认为这个线程抢到了这个锁。

对象锁和类锁:java的对象锁和类锁在锁的概念上基本上和内置锁是一致的,但是,两个锁实际是有很大的区别的,对象锁是用于对象实例方法,或者一个对象实例上的,类锁是用于类的静态方法或者一个类的class对象上的。我们知道,类的对象实例可以有很多个,但是每个类只有一个class对象,所以不同对象实例的对象锁是互不干扰的,但是每个类只有一个类锁。但是有一点必须注意的是,其实类锁只是一个概念上的东西,并不是真实存在的,它只是用来帮助我们理解锁定实例方法和静态方法的区别的。

在WEB框架开发过程中,常使用到spring框架,在spring框架里面没有做特殊设置的话,sping为我们创建的对象缺省是只有一个的,所以这个时候可以保证锁住的是同一个对象,但是如果在配置中,sping运行new出多个对象,这个时候加锁的时候就要考虑锁的是不是同一个对象了。

volatile是虚拟机提供的最轻量的同步机制(因为它的读取和写入并没有做synchronized处理),声明了该变量为volatile的话,就是告诉虚拟机,每次要用该变量时,总是要在主内存中读取。volatile并不是线程安全的,只能保证变量的可见性,不能保证原子性,例如:age = age+20,虚拟机不能保证你这个操作时原子的。

ThreadLoacl(线程变量):可以确保每个线程只使用自己那一部分的东西。例如一个变量使用ThreadLocal包装的话,那么每个线程都是使用自己的那一份变量的拷贝。可以理解为Map

你可能感兴趣的:(java基础,java)