zoukankan      html  css  js  c++  java
  • java 线程操作

    停止线程

    创建“停止标记”,thread.interrupt()

    准确的说interrupt()方法只是“告知线程该停止了”,而线程检查到该“告知”后,再通过其他的办法停止线程。

    线程调用了interrupt()方法只是打了一个停止标记,并不会立即停止。

    当程序运行时,如果调用Thread类中的以下两个方法:

    Thread.interrupted()或Thread.isInterrupted()时,可以检查当前线程的“停止标记”,

    Thread.interrupted():测试当前线程是否有“停止标记”,如果有,则返回true,然后“消除该标记”。

    Thread.isInterrupted():测试当前线程是否有“停止标记”,如果有,则返回true。

    我们可以在run方法的需要停止处轮寻Thread.isInterrupted(),当返回true时,使用以下办法停止线程。

    停止线程的方法

    1、异常法。

    先判断interrupted()状态,返回true后可以抛出异常,运行完catch后就会停止当前线程。

    建议使用此种方式终止线程,因为可以向上抛异常,使线程终止事件得以传播。

    2、thread.stop()

    stop方法已经作废了,原因如下:

    (1)线程调用stop后会被直接停止,根本无法确定被停止的线程运行到了什么地方,有可能一些必做的工作还没做完就被停止了。

    (2)线程调用stop方法会“释放该线程持有的所有锁”,无法保证原子性。

    即,假设该线程正在执行一个上锁的代码块,既然是上了锁的,那么该代码块就应该都由该线程来执行。

    可此时该线程的stop方法被调用了,那么停止了该线程的执行后,锁也被释放了,别的线程就可以再执行这个上锁的代码块,可刚刚该代码块已经执行了一半了,那么此时就无法保证锁的原子性了。

    3、return

    先判断interrupted()状态,返回true后可以使用return语句,停止线程。

    暂停与唤醒线程

    thread.suspend()与thread.resume()

    suspend额resume目前已作废,

    原因如下:

    1、在线程调用suspend时,线程如果在执行“非上锁的代码块”,则此时其他线程也可操作并改变该代码块的内容。

    那么当该线程在恢复时,其之前的内容很有可能已经被修改了,从而导致数据不同步。

    2、在线程调用suspend时,线程如果在执行“上锁的代码块”,则会导致锁被独占了,

    因为拿着锁暂停,别人又访问不了。

    object.wait()与object.notify()

    之前说的suspend是线程中的方法,而wait是Object类中的方法,也就是每个对象中都拥有的方法。

    object.wait()与object.notify()要与synchronized搭配的使用(下面的锁小节会详细介绍synchronized锁)。

    简而言之synchronized是对某一个“对象上锁”,每次线程访问同步代码块时,都要先尝试获取该对象的锁。

    wait()方法会使当前线程释放对象锁,然后当前线程“进入等待队列”,直到再次被唤醒。

    notify()方法“随机唤醒”等待队列中“同一个对象锁”的一个线程。

    notifyAll()方法会唤醒等待队列中“同一个对象锁”的“所有线程”。

    object.wait()与object.notify()成功的弥补了之前suspend的问题。

    1、object.wait()与object.notify()都要写在“同一个锁的synchronized代码块”中。

    当前线程在执行同步代码块时,并执行其中的对象锁的wait方法时,当前线程会释放掉该对象锁,并且该线程进入等待状态。

    然后其他线程可能会继续运行该同步代码块,当在同步代码块中执行了对象锁的notify方法时,会唤醒某条等待中的线程。

    二者在同一代码块中,且wait需释放锁很好理解。因为如果 wait后线程不释放锁,那么其他线程永远没机会执行该代码块,也就永远没机会执行notify方法,也就没法唤醒该线程了。

    二者在同一代码块中,解决了suspend的数据不同步问题。

    锁对象调用wait后,线程释放锁,解决了suspend的独占锁问题。

    2、即使调用了notify方法,当前线程也不会立即释放锁对象,“必须执行完毕同步代码块后(即退出synchronized代码块后)”,当前线程才会释放锁,(而wait方法是“一调用就立即释放锁”)

    condition.await()与condition.signal()

    比wait()方法更优,可以做到选择性唤醒“。

    用法与object.wait()与object.notify()类似。

    Lock对象相当于“对象锁”,

    condition相当于“一个对象锁里的对象监视器”,一个对象锁可以有多个对象监视器。

    同一把“对象锁”的同步代码块中,

    可以在“某一个condition”处暂停,然后再专门唤醒该“condition”。

    而synchronized就相当于:整个Lock对象锁中只有一个condition“对象监视器”。

    (如某个Lock代码块中,因为只有一个condition,所以每次暂停后,唤醒的肯定还是该监视器所处线程)

    Thread.sleep()

    使“当前线程”暂停执行,暂停时间为“指定的毫秒数”。

    一调用该方法,当前线程就会暂停,然后cpu就会去执行别的线程了。

    Thread.yield()

    暂停“当前线程”,“但暂停时长不确定”。

    生产者消费者模式

    等待通知模式的经典案例。

    主测试线程

    public class Main {
    
        //测试
    
        public static void main(String[] strings){
    
            //创建锁
    
            final String lock = new String("");
    
     
    
            //创建一条生产者线程,用于操作生产者对象
    
            final Producers producers= new Producers();
    
            new Thread(new Runnable() {
    
                @Override
    
                public void run() {
    
                    while (true)
    
                        producers.setValue(lock);
    
                }
    
            }).start();
    
     
    
            //创建一条消费者线程,用于操作消费对象
    
            final Consumer consumer= new Consumer();
    
            new Thread(new Runnable() {
    
                @Override
    
                public void run() {
    
                    while (true)
    
                        consumer.getValue(lock);
    
                }
    
            }).start();
    
        }
    
    }

    线程间操作的值:

    //线程间操作的值
    
    public class ValueClass {
    
        public static String value = "";
    
    }

    生产者:

    //生产者对象,目的是产生某个值给消费者用。
    
    public class Producers {
    
        public void setValue(Object lock){
    
            try {
    
                synchronized (lock){
    
                    //“第一步”,如果当前value中有值,就等待(有值就不造值了,等该值被消耗了再造),没值就造值。
    
                    if (!ValueClass.value.equals("")){
    
                        lock.wait();
    
                    }
    
     
    
                    //“第二步”,造出当前时间戳,并赋值给value供消费者消费
    
                    String value = System.currentTimeMillis()+"";
    
                    ValueClass.value = value;
    
                    System.out.println("生产者已生产时间戳:"+value);
    
     
    
                    //“第三步”,通知等待消费的消费者,可以消费了
    
                    lock.notify();
    
                }
    
            }catch (InterruptedException e){
    
                e.printStackTrace();
    
            }
    
        }
    
    }

    消费者:

    //消费者对象,目的是获取某个生产者生产的值
    
    public class Consumer {
    
        public void getValue(Object lock){
    
            try {
    
                synchronized (lock){
    
                    //“第一步”,如果没有值,就等待(等待生产者造值)
    
                    if (ValueClass.value.equals("")){
    
                        lock.wait();
    
                    }
    
     
    
                    //“第四步”,从ValueClass中消费值,并将Class中的值赋值为"",表示消费完了。
    
                    System.out.println("消费者消费了时间戳:"+ValueClass.value);
    
                    ValueClass.value = "";
    
     
    
                    //“第五步”,通知生产者,表示你可以接着造值了(又回到第二步)
    
                    lock.notify();
    
                }
    
            }catch (InterruptedException e){
    
                e.printStackTrace();
    
            }
    
        }
    
    }

    结果:

     

    其它操作

    thread.join()

    主线程创建子线程,如果主线程想确保子线程运行完后再结束,就可以用到join方法了。

    join()方法的作用是“等待线程对象销毁

  • 相关阅读:
    python生成CSV文件并发送邮件
    Live2d Test Env
    Live2d Test Env
    Live2d Test Env
    Live2d Test Env
    Live2d Test Env
    Live2d Test Env
    Live2d Test Env
    Live2d Test Env
    扔鸡蛋
  • 原文地址:https://www.cnblogs.com/red-code/p/7763837.html
Copyright © 2011-2022 走看看