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


    初始线程:
    1.新建线程
    1)继承Thread类 2)实现Runnable接口
    2.线程终止
    除非你很清楚你在做什么,否则不要随便使用stop()方法来停止一个线程。因为stop()方法太过于暴力,强行把执行到一半的线程终止,可能会引起一些数据不一致的问题。 通过定义标记变量stopme,当stopme=true时,在run内部返回结果或跳出循环。
    3.线程中断
    线程中断是一种重要的线程协作机制。严格地讲,线程中断并不会使线程立即退出,而是给线程发送一个通知,告知目标线程,有人希望你退出啦!至于目标线程接到通知后如何处理,则完全由目标线程自行决定。
    Thread类中与线程中断有关的,有三个方法:

    注意:Thread.sleep()方法由于中断而抛出异常,此时,它会清除中断标记,如果不加处理,那么在下一次循环开始时,就无法捕获这个中断,故在异常处理中,再次设置中断标记位。
    01 public static void main(String[] args) throws InterruptedException {
    02 Thread t1=new Thread(){
    03 @Override
    04 public void run(){
    05 while(true){
    06 if(Thread.currentThread().isInterrupted()){
    07 System.out.println("Interruted!”);
    08 break;
    09 }
    10 try {
    11 Thread.sleep(2000);
    12 } catch (InterruptedException e) {
    13 System.out.println("Interruted When Sleep”);
    14 //设置中断状态
    15 Thread.currentThread().interrupt();
    16 }
    17 Thread.yield();
    18 }
    19 }
    20 };
    21 t1.start();
    22 Thread.sleep(2000);
    23 t1.interrupt();
    24 }
    4.等待(wait)和通知(notify)
    Object类提供两个重要的接口,线程等待wait()方法和通知notify()方法,并不是Thread类中的方法。
    当线程A中,调用了obj.wait()方法,那么线程A就会停止继续执行,而转为等待状态。等待到何时结束呢?线程A会一直等到其他线程调用了obj.notify()方法为止。这时,obj对象就俨然成为多个线程之间的有效通信手段。
    注意:Object.wait()和Thread.sleep()方法都可以让线程等待若干时间。除了wait()可以被唤醒外,另外一个主要区别就是wait()方法会释放目标对象的锁,而Thread.sleep()方法不会释放任何资源。
    wait和notify()调用前,也必须获得object的监视器。
    5.挂起(suspend)和继续执行(resume)线程
    属于Thread的api,不推荐使用,因为suspend()在导致线程暂停的同时,并不会去释放任何锁资源。此时,其他任何线程想要访问被它暂用的锁时,都会被牵连,导致无法正常继续运行。直到对应的线程上进行了resume()操作,被挂起的线程才能继续,从而其他所有阻塞在相关锁上的线程也可以继续执行。但是,如果resume()操作意外地在suspend()前就执行了,那么被挂起的线程可能很难有机会被继续执行。
    6.等待线程结束(join)和谦让(yield)
    此时,这个线程就需要等待依赖线程执行完毕,才能继续执行。JDK Thread提供了join()操作来实现这个功能,

    第一个join()方法表示无限等待,它会一直阻塞当前线程,直到目标线程执行完毕。第二个方法给出了一个最大等待时间,如果超过给定时间目标线程还在执行,当前线程也会因为“等不及了”,而继续往下执行。

    join()的本质是让调用线程 wait()在当前线程对象实例上,,值得注意的一点是:不要在应用程序中,在Thread对象实例上使用类似wait()或者notify()等方法,因为这很有可能会影响系统API的工作,或者被系统API所影响。

    另外一个比较有趣的方法,是Thread.yield(),它的定义如下:public static native void yield();
    这是一个静态方法,一旦执行,它会使当前线程让出CPU。但要注意,让出CPU并不表示当前线程不执行了。当前线程在让出CPU后,还会进行CPU资源的争夺,但是是否能够再次被分配到,就不一定了。因此,对Thread.yield()的调用就好像是在说:我已经完成一些最重要的工作了,我应该是可以休息一下了,可以给其他线程一些工作机会啦!如果你觉得一个线程不那么重要,或者优先级非常低,而且又害怕它会占用太多的CPU资源,那么可以在适当的时候调用Thread.yield(),给予其它线程机会。

    分门别类的管理:线程组
    ThreadGroup tg = new ThreadGroup(“tg”);
    Thread t1 = new Thread(tg, new ThreadGroupName(), "T1”);
    tg.activeCount();
    tg.list();
    烈建议大家在创建线程和线程组的时候,给它们取一个好听的名字,方便调试

    7.驻守后台:守护线程(Daemon)
    守护线程是一种特殊的线程,就和它的名字一样,它是系统的守护者,在后台默默地完成一些系统性的服务,比如垃圾回收线程、JIT线程就可以理解为守护线程。与之相对应的是用户线程,用户线程可以认为是系统的工作线程,它会完成这个程序应该要完成的业务操作。如果用户线程全部结束,这也意味着这个程序实际上无事可做了。守护线程要守护的对象已经不存在了,那么整个应用程序就自然应该结束。因此,当一个Java应用内,只有守护线程时,Java虚拟机就会自然退出。


    8.先干重要的事:线程优先级
    在Java中,使用1到10表示线程优先级。一般可以使用Thread内置的三个静态标量表示:
    public final static int MIN_PRIORITY = 1;
    public final static int NORM_PRIORITY = 5;
    public final static int MAX_PRIORITY = 10;
    数字越大则优先级越高,但有效范围在1到10之间。下面的代码展示了优先级的作用。高优先级的线程倾向于更快地完成。

    9.线程安全的概念与synchronized
    线程安全是并行程序的根本和根基。
    大家还记得那个多线程读写long型数据的案例吧!这就是一个典型的反例。但在使用volatile关键字后,这种错误的情况有所改善。但是,volatile并不能真正的保证线程安全。它只能确保一个线程修改了数据后,其他线程能够看到这个改动。但当两个线程同时修改某一个数据时,却依然会产生冲突。
    synchronized的用法
    •指定加锁对象:对给定对象加锁,进入同步代码前要获得给定对象的锁。
    •直接作用于实例方法:相当于对当前实例加锁,进入同步代码前要获得当前实例的锁。
    •直接作用于静态方法:相当于对当前类加锁,进入同步代码前要获得当前类的锁。

    除了用于线程同步、确保线程安全外,syn-chronized还可以保证线程间的可见性和有序性。从可见性的角度上讲,synchronized可以完全替代volatile的功能,只是使用上没有那么方便。就有序性而言,由于synchronized限制每次只有一个线程可以访问同步块,因此,无论同步块内的代码如何被乱序执行,只要保证串行语义一致,那么执行结果总是一样的。而其他访问线程,又必须在获得锁后方能进入代码块读取数据,因此,它们看到的最终结果并不取决于代码的执行过程,从而有序性问题自然得到了解决(换言之,被synchronized限制的多个线程是串行执行的)。

    在Java中,Integer属于不变对象。也就是对象一旦被创建,就不可能被修改。也就是说,如果你有一个Integer代表1,那么它就永远表示1,你不可能修改Integer的值,使它为2。那如果你需要2怎么办呢?也很简单,新建一个Integer,并让它表示2即可。
    使用javap反编译i++ 实际上使用了Integer.valueOf()方法新建了一个新的Integer对象,并将它赋值给变量i。也就是说,i++在真实执行时变成了:i=Integer.valueOf(i.intValue()+1);
    进一步查看Integer.valueOf(),我们可以看到:public static Integer valueOf(int i) { assert IntegerCache.high >= 127; if (i >= IntegerCache.low && i <= IntegerCache.high) return IntegerCache.cache[i + (-IntegerCache.low)]; return new Integer(i);}

    使用jstack工具显示程序的线程信息,如下所示。其中jps可以显示当前系统中所有的Java进程。而jstack可以打印给定Java进程的内部线程及其堆栈。

    C:Usersgeym >jps
    14240 HashMapMultiThread
    1192 Jps
    C:Usersgeym >jstack 14240

  • 相关阅读:
    记一次性能优化经历
    把一个一中的字段更新另一个表中的t-sql
    Dapper 中使用sql in 关键字查询
    HTML5 学习笔记 应用程序缓存
    HTML5学习笔记 Web存储
    HTML5 学习笔记 表单属性
    HTML5学习笔记 Geolocation(地理定位)
    vim插件之delimitMate.vim
    vim 插件之 surround.vim
    vim 脚本之快速打印log
  • 原文地址:https://www.cnblogs.com/756623607-zhang/p/6850860.html
Copyright © 2011-2022 走看看