多线程(二)

(一)如何正确的停止一个线程?

停止一个线程意味着在任务处理完之前停止,也就是放弃当前的操作。停止一个线程可以yogaThread.stop()方法,但是最好不要用它,因为该方法是不安全的,而且该方法已经被废弃。

在java中有三种停止线程的方法:

  1、是线程正常退出,也就是当run()方法完成后种植线程

  2、使用stop()方法强行终止,但是不推荐使用该方法,该方法与suspend,resume医用已经被废弃

  3、使用interrupt方法终端线程,Thread.interrupt()方法不会中断一个正在运行的线程。这一方法实际上完成的是,在线程受到阻塞时抛出一个中断信号,这样线程就得以退出阻塞的状态。更确切的说,如果线程被Object.wait, Thread.join和Thread.sleep三种方法之一阻塞,那么,它将接收到一个中断异常(InterruptedException),从而提早地终结被阻塞状态。 

           因此,如果线程被上述几种方法阻塞,正确的停止线程方式是设置共享变量,并调用interrupt()(注意变量应该先设置)。如果线程没有被阻塞,这时调用interrupt()将不起作用;否则,线程就将得到异常(该线程必须事先预备好处理此状况),接着逃离阻塞状态。在任何一种情况中,最后线程都将检查共享变量然后再停止这个示例描述了该技术。 

 1 class Example3 extends Thread {
 2   volatile boolean stop = false;
 3   public static void main( String args[] ) throws Exception {
 4    Example3 thread = new Example3();
 5    System.out.println( "Starting thread..." );
 6    thread.start();
 7    Thread.sleep( 3000 );
 8    System.out.println( "Asking thread to stop..." );
 9    thread.stop = true;//如果线程阻塞,将不会检查此变量
10    thread.interrupt();
11    Thread.sleep( 3000 );
12    System.out.println( "Stopping application..." );
13    //System.exit( 0 );
14   }
15 
16   public void run() {
17     while ( !stop ) {
18      System.out.println( "Thread running..." );
19       try {
20       Thread.sleep( 1000 );
21       } catch ( InterruptedException e ) {
22       System.out.println( "Thread interrupted..." );
23       }
24     }
25    System.out.println( "Thread exiting under request..." );
26   }
27 }

一旦Thread.interrupt()被调用,线程便收到一个异常,于是逃离了阻塞状态并确定应该停止。运行以上代码将得到下面的输出: 

Starting thread... 
Thread running... 
Thread running... 
Thread running... 
Asking thread to stop... 
Thread interrupted... 
Thread exiting under request... 
Stopping application...

(二)线程安全

线程安全就是多线程访问同一代码,不会产生不确定的结果。

如何保证线程安全? 

(1)最简单的方式是加入synchronized关键字,这会获取对象锁,其他线程函数将被一直阻塞

(2)使用锁

区别:

a.Lock使用起来比较灵活,但需要手动释放和开启;

b.Lock只适用于与代码块锁,而synchronized对象之间是互斥!

 (三)synchronized如何使用

synchronized是Java中的关键字,是一种同步锁。它修饰的对象有以下几种:
1). 修饰一个代码块,被修饰的代码块称为同步语句块,其作用的范围是大括号{}括起来的代码,作用的对象是调用这个代码块的对象;
2). 修饰一个方法,被修饰的方法称为同步方法,其作用的范围是整个方法,作用的对象是调用这个方法的对象;
3). 修改一个静态的方法,其作用的范围是整个静态方法,作用的对象是这个类的所有对象;
4). 修改一个类,其作用的范围是synchronized后面括号括起来的部分,作用主的对象是这个类的所有对象。

(四)synchronized和Lock的区别

http://www.cnblogs.com/baizhanshi/p/6419268.html

总结来说,Lock和synchronized有以下几点不同:

  1)Lock是一个接口,而synchronized是Java中的关键字,synchronized是内置的语言实现;

  2)synchronized发生异常时,会自动释放线程占有的锁,因此不会导致死锁现象发生;而Lock在发生异常时,如果没有主动通过unLock()去释放锁,则很可能造成死锁现象,因此使用Lock时需要在finally中释放锁;

  3)Lock可以让等待锁的线程响应中断,而synchronized却不行,使用synchronized时,等待的线程会一直等待下去,不能够响应中断;

  4)通过Lock可以知道有没有成功获取锁,而synchronized却无法办到。

  5)Lock可以提高多个线程进行读操作的效率。

  在性能上来说,如果竞争资源不激烈,两者的性能是差不多的,而当竞争资源非常激烈时(即有大量线程同时竞争),此时Lock的性能要远远优于synchronized。所以说,在具体使用时要根据适当情况选择。

主要相同点:Lock能完成synchronized所实现的所有功能
主要不同点:Lock有比synchronized更精确的线程语义和更好的性能。Lock的锁定是通过代码实现的,而synchronized是在JVM层面上实现的,synchronized会自动释放锁,而Lock一定要求程序员手工释放,并且必须在finally从句中释放。Lock还有更强大的功能,例如,它的tryLock方法可以非阻塞方式去拿锁。Lock锁的范围有局限性,块范围,而synchronized可以锁住块、对象、类,wait、notifyf必须在synchronized中执行。

       1)Lock不是Java语言内置的,synchronized是Java语言的关键字,因此是内置特性。Lock是一个类,通过这个类可以实现同步访问;

  2)Lock和synchronized有一点非常大的不同,采用synchronized不需要用户去手动释放锁,当synchronized方法或者synchronized代码块执行完之后,系统会自动让线程释放对锁的占用;而Lock则必须要用户去手动释放锁,如果没有主动释放锁,就有可能导致出现死锁现象。

ReentrantLock(可重入锁)是唯一实现了Lock接口的类。

(五)sleep和wait的区别(考察是否会释放锁)

sleep()方法是Thread类中方法,而wait()方法是Object类中的方法。
sleep()方法导致了程序暂停执行指定的时间,让出cpu该其他线程,但是他的监控状态依然保持者,当指定的时间到了又会自动恢复运行状态,在调用sleep()方法的过程中,线程不会释放对象锁。而当调用wait()方法的时候,线程会放弃对象锁,进入等待此对象的等待锁定池,只有针对此对象调用notify()方法后本线程才进入对象锁定池准备。

面试题:http://www.cnblogs.com/dolphin0520/p/3932934.html

原文地址:https://www.cnblogs.com/wangleBlogs/p/7365677.html