多线程补充、多线程问题及处理、线程的同步及相关内容

来源:互联网 发布:亚马逊 知乎 编辑:程序博客网 时间:2024/06/06 02:07

多线程补充:
线程睡眠sleep():

    执行该方法可使当前线程睡眠(停止状态)若干毫秒,线程由运行状态进入不可运行状态,睡眠时间过后线程再次进入可运行状

态。//Thread.sleep(1000)休眠1000毫秒(一秒)。

暂停线程yield():

    调用yield()方法可暂停当前线程执行,将CPU资源让出来,允许其他线程执行。该线程任给从处于可运行状态,不转变为为堵塞状态。yield()方法

的优点是保证有工作时不会让CPU闲置,主要用于编写多个合作线程,也适用于强制线程间的合作。Thread.yield();


连接线程join():

    调用join()方法可使当前线程暂停执行,等待调用该方法的线程结束后再继续执行本线程。它有三种调用格式:
public final void join() throws InterruptedException
public final void join(long millis) throws InterruptedException
public final void join(long millis,int nanos) throws InterruptedException
等待调用该方法的线程结束,或者最多等待millis毫秒+nanos纳秒后,再继续执行本线程。

中断线程interrupt():

public void interrupt()
public boolean isInterrupted()
public static boolean interrupted()

interrupt()方法可为线程设置一个中断标记,以便于run()方法运行时使用isInterrupted()方法能够检测到。此时,线程在sleep()之类的方法中被堵

塞时,由sleep()方法抛出一个InterruptedException异常,然后捕获这个异常以处理超时。


多线程问题及处理、线程的同步及相关内容:

    多线程编程为程序开发带来很多便利的同时也有一些问题,而这些问题是在程序开发中必须进行处理的。这些问题的核心是如果多个线程访问同一

个资源时,如变量、文件等,如何保证安全?在多线程编程中,这种会被多个线程访问的资源叫做临界资源。运行时会出现不同的情况,比如一个大于

零的变量进行自减,而当多线程同时访问这个变量时有时会出现访问的是零变量这不符合程序的运行,在银行的应用中两个人同时取一个账户的钱不能

让他去两次吧等等。。。所以这就需要处理了,而解决问题的最基本、最简单的思路就是使用同步关键字synchroniazed(。。。线程的同步)。    
    synchronized关键字是一个修饰符,可以修饰方法或代码块。作用就是:对于同一个对象(不是一个类的不同对象),当多个线程都同时调用该方

法或代码块时,必须依次执行,也就是说,如果两个或两个以上的线程同时执行该段代码,如果一个线程已经开始执行该段代码,则另外的线程必须等

待这个线程执行完后才能开始执行。

synchronized有两种使用方法:

一种是函数,一个是同步代码块。

使用函数:
public class SaleTicket implements Runnable{
 private int ticket=100;
 public void run(){
   while(true){
    show();
   }
  }
  public synchronized void show(){
   if(ticket>0){
    try {
     Thread.sleep(500);
    } catch (InterruptedException e) {
    // TODO Auto-generated catch block
       e.printStackTrace();
    }
    System.out.println(Thread.currentThread().getName()+"....."+"第"+ticket--+"号票");
    }
   }
 }
     public static void main(String[] args) {
  SaleTicket st=new SaleTicket();
  Thread t1=new Thread(st);
  Thread t2=new Thread(st);
  t1.start();
  t2.start();
 }
}

使用同步代码块:

public class SaleTicket implements Runnable{
 private int ticket=100;
 Object s=new Object();
 public void run() { 
  while(true){
   synchronized(this){    
    if(ticket>0){
     try {
      Thread.sleep(100);
     } catch (InterruptedException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
     }
     System.out.println(Thread.currentThread().getName()+"....."+"第"+ticket--+"号票");
    }else{
     break;
    }
    }
  }
 } 
 public static void main(String[] args) {
  SaleTicket st=new SaleTicket();
  Thread t1=new Thread(st);
  Thread t2=new Thread(st);
  t1.start();
  t2.start();
 }
}

互斥锁:

    每个对象都对应于一个可称为“互斥锁”的标记,这个标记用来保证在任一时刻,只能有一个线程访问该对象。    Java对象默认是可以被多个线

程共用的,只是在需要时才启动“互斥锁”机制,成为专用对象。
   
关键字synchronized用来与对象的互斥锁联系
   
当某个对象用synchronized修饰时,表明该对象已启动“互斥锁”机制,在任一时刻只能由一个线程访问,即使该线程出现堵塞,该对象的被锁定

状态也不会解除,其他线程任不能访问该对象。
同步好处:决了线程安全问题同步弊端:
    降低了运行效率(判断锁是较为消耗资源的)
    同步嵌套,容易出现死锁

死锁:

    两个线程A、B用到同一个对象s(s为共享资源),且线程A在执行中要用到B运行后所创造的条件。在这种前提下A先开始运行,进入同步块后,对象s

被锁定,接着线程A因等待B运行结束而进入阻塞状态,于是B开始运行,但因无法访问对象s,线程B也进入阻塞状态,等待s被线程A解锁。最终的结果:

两个线程互相等待,都无法运行。

线程同步通信
   
    为避免死锁,就应该让线程在进入阻塞状态时尽量释放其锁定的资源,以为其他的线程提供运行的机会,Object类中定义了几个有用的方法:wait

()、notify()、notifyAll()。
    wait():被锁定的对象可以调用wait()方法,这将导致当前线程被阻塞并释放该对象的互斥锁,即解除了wait()方法当前对象的锁定状态,其他的

线程就有机会访问该对象。
    notify():唤醒调用wait()方法后被阻塞的线程。每次运行该方法只能唤醒一个线程。
    notifyAll():唤醒所有调用wait()方法被阻塞的线程。


线程的同步解决生产者-消费者问题    限制公共缓冲区不能被两个线程同时访问,需要使用互斥锁,即用synchronized来标识同步资源。
    但加了互斥锁以后有可能会造出死锁。这时需要wait()方法和notify()方法--当前线程被阻塞并释放该对象的互斥锁。