多线程编程技巧

来源:互联网 发布:怎么一键复制淘宝店铺 编辑:程序博客网 时间:2024/06/07 03:37


java中,多线程类需要继承Thread或实现Runnable接口,

在Run函数中执行多线程代码,但是需要用Start()函数开始执行。多线程并行执行,执行的顺序取决于本地操作系统给谁分配系统资源。

Runnable共享资源的方法:

a、如果每个线程执行的代码相同,可以使用同一个Runnable对象,这个对象中有共享数据。卖票就可以这样做,每个窗口都在做卖票任务,卖的票都是同一个数据。

b、如果每个线程执行的代码不同,就需要使用不同的Runnable对象,有两种方式实现Runnable对象之间的数据共享:
1)、将共享数据单独封装到一个对象中,同时在对象中提供操作这些共享数据的方法,可以方便实现对共享数据各项操作的互斥和通信。
2、)将各个Runnable对象作为某个类的内部类,共享数据作为外部类的成员变量,对共享数据的操作方法也在外部类中提供,以便实现互斥和通信,内部类的Runnable对象调用外部类中操作共享数据的方法即可。

如:  public class Thread1 implements Runnable

private int a[10];                           -------这里的int型数据是被Thread1实例化对象共用的

public void Run()

{}

}


多线程API函数和常量含义:

static int MAX_PRIORITY
          线程可以具有的最高优先级。
static int MIN_PRIORITY
          线程可以具有的最低优先级。
static int NORM_PRIORITY
          分配给线程的默认优先级。
 
构造方法摘要
Thread(Runnable target)
          分配新的 Thread 对象。
Thread(String name)
          分配新的 Thread 对象。
 
 
方法摘要
static Thread currentThread()
          返回对当前正在执行的线程对象的引用。
 ClassLoader getContextClassLoader()
          返回该线程的上下文 ClassLoader。
 long getId()
          返回该线程的标识符。
 String getName()
          返回该线程的名称。
 int getPriority()
          返回线程的优先级。
 Thread.State getState()
          返回该线程的状态。
 ThreadGroup getThreadGroup()
          返回该线程所属的线程组。
static boolean holdsLock(Object obj)
          当且仅当当前线程在指定的对象上保持监视器锁时,才返回 true。
 void interrupt()
          中断线程。
static boolean interrupted()
          测试当前线程是否已经中断。
 boolean isAlive()
          测试线程是否处于活动状态。
 boolean isDaemon()
          测试该线程是否为守护线程。
 boolean isInterrupted()
          测试线程是否已经中断。
 void join()
          等待该线程终止。
 void join(long millis)
          等待该线程终止的时间最长为 millis 毫秒。
 void join(long millis, int nanos)
          等待该线程终止的时间最长为 millis 毫秒 + nanos 纳秒。
 void resume()
          已过时。 该方法只与 suspend() 一起使用,但 suspend() 已经遭到反对,因为它具有死锁倾向。有关更多信息,请参阅为何 Thread.stop、Thread.suspend 和 Thread.resume 遭到反对?。
 void run()
          如果该线程是使用独立的 Runnable 运行对象构造的,则调用该 Runnable 对象的 run 方法;否则,该方法不执行任何操作并返回。
 void setContextClassLoader(ClassLoader cl)
          设置该线程的上下文 ClassLoader。
 void setDaemon(boolean on)
          将该线程标记为守护线程或用户线程。
static void setDefaultUncaughtExceptionHandler(Thread.UncaughtExceptionHandler eh)
          设置当线程由于未捕获到异常而突然终止,并且没有为该线程定义其他处理程序时所调用的默认处理程序。
 void setName(String name)
          改变线程名称,使之与参数 name 相同。
 void setPriority(int newPriority)
          更改线程的优先级。
 void setUncaughtExceptionHandler(Thread.UncaughtExceptionHandler eh)
          设置该线程由于未捕获到异常而突然终止时调用的处理程序。
static void sleep(long millis)
          在指定的毫秒数内让当前正在执行的线程休眠(暂停执行)。
static void sleep(long millis, int nanos)
          在指定的毫秒数加指定的纳秒数内让当前正在执行的线程休眠(暂停执行)。
 void start()
          使该线程开始执行;Java 虚拟机调用该线程的 run 方法。
 void stop()
          已过时。 该方法具有固有的不安全性。如果目标线程等待很长时间(例如基于一个条件变量),则应使用 interrupt 方法来中断该等待。

多线程状态转换:

线程在一定条件下,状态会发生变化。线程变化的状态转换图如下:
 
1、新建状态(New):新创建了一个线程对象。
2、就绪状态(Runnable):线程对象创建后,其他线程调用了该对象的start()方法。该状态的线程位于可运行线程池中,变得可运行,等待获取CPU的使用权。
3、运行状态(Running):就绪状态的线程获取了CPU,执行程序代码。
4、阻塞状态(Blocked):阻塞状态是线程因为某种原因放弃CPU使用权,暂时停止运行。直到线程进入就绪状态,才有机会转到运行状态。阻塞的情况分三种:
(一)、等待阻塞:运行的线程执行wait()方法,JVM会把该线程放入等待池中。
(二)、同步阻塞:运行的线程在获取对象的同步锁时,若该同步锁被别的线程占用,则JVM会把该线程放入锁池中。
(三)、其他阻塞:运行的线程执行sleep()或join()方法,或者发出了I/O请求时,JVM会把该线程置为阻塞状态。当sleep()状态超时、join()等待线程终止或者超时、或者I/O处理完毕时,线程重新转入就绪状态。
5、死亡状态(Dead):线程执行完了或者因异常退出了run()方法,该线程结束生命周期。
 
线程的调度
1、调整线程优先级:Java线程有优先级,优先级高的线程会获得较多的运行机会。
Java线程的优先级用整数表示,取值范围是1~10,Thread类有以下三个静态常量:
static int MAX_PRIORITY
          线程可以具有的最高优先级,取值为10。
static int MIN_PRIORITY
          线程可以具有的最低优先级,取值为1。
static int NORM_PRIORITY
          分配给线程的默认优先级,取值为5。
Thread类的setPriority()和getPriority()方法分别用来设置和获取线程的优先级。
每个线程都有默认的优先级。主线程的默认优先级为Thread.NORM_PRIORITY。
线程的优先级有继承关系,比如A线程中创建了B线程,那么B将和A具有相同的优先级。
JVM提供了10个线程优先级,但与常见的操作系统都不能很好的映射。如果希望程序能移植到各个操作系统中,应该仅仅使用Thread类有以下三个静态常量作为优先级,这样能保证同样的优先级采用了同样的调度方式。
2、线程睡眠:Thread.sleep(long millis)方法,使线程转到阻塞状态。millis参数设定睡眠的时间,以毫秒为单位。当睡眠结束后,就转为就绪(Runnable)状态。sleep()平台移植性好。
3、线程等待:Object类中的wait()方法,导致当前的线程等待,直到其他线程调用此对象的 notify() 方法或 notifyAll() 唤醒方法。这个两个唤醒方法也是Object类中的方法,行为等价于调用 wait(0) 一样。
4、线程让步:Thread.yield() 方法,暂停当前正在执行的线程对象,把执行机会让给相同或者更高优先级的线程。
5、线程加入:join()方法,等待其他线程终止。在当前线程中调用另一个线程的join()方法,则当前线程转入阻塞状态,直到另一个进程运行结束,当前线程再由阻塞转为就绪状态。
6、线程唤醒:Object类中的notify()方法,唤醒在此对象监视器上等待的单个线程。如果所有线程都在此对象上等待,则会选择唤醒其中一个线程。选择是任意性的,并在对实现做出决定时发生。线程通过调用其中一个 wait 方法,在对象的监视器上等待。 直到当前的线程放弃此对象上的锁定,才能继续执行被唤醒的线程。被唤醒的线程将以常规方式与在该对象上主动同步的其他所有线程进行竞争;例如,唤醒的线程在作为锁定此对象的下一个线程方面没有可靠的特权或劣势。类似的方法还有一个notifyAll(),唤醒在此对象监视器上等待的所有线程。
注意:Thread中suspend()和resume()两个方法在JDK1.5中已经废除,不再介绍。因为有死锁倾向。
7、常见线程名词解释
主线程:JVM调用程序mian()所产生的线程。
当前线程:这个是容易混淆的概念。一般指通过Thread.currentThread()来获取的进程。
后台线程:指为其他线程提供服务的线程,也称为守护线程。JVM的垃圾回收线程就是一个后台线程。
前台线程:是指接受后台线程服务的线程,其实前台后台线程是联系在一起,就像傀儡和幕后操纵者一样的关系。傀儡是前台线程、幕后操纵者是后台线程。由前台线程创建的线程默认也是前台线程。可以通过isDaemon()和setDaemon()方法来判断和设置一个线程是否为后台线程。
转载自 “熔 岩” 博客,请务必保留此出处http://lavasoft.blog.51cto.com/62575/27069
0 0
原创粉丝点击