如何java让线程暂停停,又能随时唤醒

一、多线程之间的通信。
    就是多个线程在操作同一份数据, 但是操作的方法不同。
    如: 对于同一个存储块,其中有两个存储位:name & sex, 现有两个线程,一个向其中存放数据,一个打印其中的数据。
    为了解决上述问题中的安全问题(在存放线程进行存放操作的时候, 打印线程不能对共有数据进行操作),所以应当对两个线程& & & &操作共有数据的代码部分进行同步(使用synchronized(),来进行同步,
注意 :使用同一个对象作为同步锁。
二、等待唤醒机制。
    在上述案例实现过后运行,会发现:打印结果顺序并不是按照存放顺序进行的, 所以在此处就引入了等待唤醒机制。
        解释:就是在一个线程进行了规定操作后,就进入等待状态(wait()), 等待其他线程执行完他们的指定代码过后 再将其唤醒(notify())。
     & & 在有多个线程进行等待时,
如果需要,可以使用
notifyAll()来唤醒所有的等待线程。
    所使用的方法(关键字):
          对象名.wait();
在其他线程调用此对象的 notify() 方法或 notifyAll() 方法前,导致当前线程等待。
          对象名.notify();
唤醒在此对象监视器上等待的单个线程。
          对象名.notifyAll();唤醒在此对象监视器上等待的所有线程。
        注意:以上方法(关键字),都必须使用在同步中,因为其需要对持有该对象监视器所有权(锁)的线程进行操作。
      所以必须使用在同步中,因为只有同步中的线程才具有该对象监视器的所有权(锁),
        wait()和sleep()一样,都会抛出 InterruptedException 异常。
        而且,以上方法都定义在类:Object中
            是因为,这些方法在操作同步中的线程的时候,都必须标示其所操作线程所持有的锁(被该锁的对象调用),
          而只有同一个对象监视器下(同一个锁上的)的被等待线程,可以被持有该锁的线程唤醒,(无法唤醒不同锁上的线程)
            即:
等待和唤醒的必须是同一个对象的监视器下(同一个锁上)的线程。
          而锁可以是任意已近确定的对象, 能被任意对象调用的方法应当定义在 Object类中。
      监视器(锁): 同一个对象的监视器下(同一个锁上)的线程,一次只能执行一个:就是拥有监视器所有权(持有锁)的那一个线程。
三、接口Lock和 接口Condition
    注:在使用Lock 与Condition 时,必须引入其工具包:import
java.util.concurrent.locks.*
             在jdk1.5以上,为了解决多个线程同时在对一份共享数据进行不同操作时出现的安全问题(要么陷入所有线程同时等待的状态、
          要么每次唤醒所有等待线程的问题),
              其为我们提供了新的
锁工具: Lock来替换 synchronized , 由 Lock对象所创建的绑定于该Lock对象的 condition对象
          &&替换了object类中的wait,notify操作。
    1、Lock接口, 已知实现该接口的类: ReentrantLock, ReentrantReadWriteLock.ReadLock, ReentrantReadWriteLock.WriteLock
      1)、 ReentrantLock(大体功能与 synchronized相当,不过可以绑定多个condition)
            构造方法:ReentrantLock()
创建一个 ReentrantLock 的实例。
                 ReentrantLock(boolean fair)
创建一个具有给定公平策略的 ReentrantLock
            常用方法: void lock()
:获取一个锁。
                 &void unlock() :释放该锁。
                 &Condition newCondition()
返回用来与此 Lock 实例一起使用的 Condition 实例。
    2、Contition接口, 已知实现类:AbstractQueuedLongSynchronizer.ConditionObject, AbstractQueuedSynchronizer.ConditionObject(暂时不学习)
            常用方法:void await()
造成当前线程在接到信号或被中断之前一直处于等待状态。
                 void signal()
唤醒一个等待线程。
                 void signalAll()
唤醒所有等待线程。
        常见代码示例:
          class BoundedBuffer {
            final Lock lock = new ReentrantLock();
//创建一个Lock的子类对象 lock
            final Condition notFull
= lock.newCondition();
//调用lock的newCondition方法,创建一个condition子类对象 notFull
            final Condition notEmpty = lock.newCondition();
//调用lock的newCondition方法,创建一个condition子类对象 notEmpty
            public void put(Object x) throws InterruptedException {
                lock.lock();
                try {
                    while (判断语句)
                      notFull.await();
//判断成功,线程等待于notFull下。
                    操作代码
                    notEmpty.signal();
//唤醒notEmpty下的等待线程。
                } finally {
//保证其后语句执行。
                     lock.unlock();
//释放锁。
                }
            }
            public Object take() throws InterruptedException {
                lock.lock();
                try {
                  while ()
                    notEmpty.await();
                  操作代码
                  notFull.signal();
                } finally {
                      lock.unlock();
                }
            }
          }
四、停止线程
      注:在旧版本的jdk中存在stop方法,但是在新版本中。此方法被过时。
      线程停止的原理: 当 run方法中的代码执行完毕过后,就自动停止该线程。
          1、当线程中是循环代码的时候, 只要控制住循环结束,就能够结束该线程。
              特殊情况:当线程中有wait()语句或者await()等语句时,会使得线程处于冻结状态, 让控制循环结束的代码或者标记无法执行或读取,
            那么线程就不会结束。
              当所有线程都陷入冻结,没有指定方法解除冻结时,就需要我们强制清除冻结状态,这样就可以操作标记使循环结束。
              Thread类中提供了这一方法:
Interrupt()方法,(等待型语句本身会有一个InterrptedException异常的判断,
                      只要被Interrupt方法打断冻结,就会抛出这一异常, 我们就可以在异常处理语句中建立循环结束的标记)。
五、守护线程
    Thread类中有一个方法,调用该方法并传入
true ,能将该线程定义为 守护线程(后台线程),
        该方法是: void setDaemon(boolean on)
将该线程标记为守护线程或用户线程。(调用时应当传入true)。
      注意: 1、将该线程标记为守护线程或用户线程。当正在运行的线程都是守护线程时,Java 虚拟机退出。
        (就是说,后台线程依赖于前台线程)
         &2、该方法必须在启动线程前调用。
        示例:
Thread t = new Thread();
            t.setDaemon(true);
            t.start();
          此时的线程 t 为守护线程。
六、Join方法。
    vpi解释:void join()
等待该线程终止。
    在线程A执行的时候,碰到了B线程.join方法时,A线程就会等待,等B线程执行完,才继续执行。
    (当在调用join方法时传入参数: long millis 时,表示 A线程等待B线程执行时间最长为millis毫秒。)
      join可以用来临时加入线程执行。
阅读(...) 评论()3887人阅读
Java面试题(12)
sleep()方法(休眠)是线程类(Thread)的静态方法,调用此方法会让当前线程暂停执行指定的时间,
将执行机会(CPU)让给其他线程,但是对象的锁依然保持,因此休眠时间结束后会自动恢复(线程回到就绪状态,请参考第66题中的线程状态转换图)。
wait()是Object类的方法,调用对象的wait()方法导致当前线程放弃对象的锁(线程暂停执行),进入对象的等待池(wait
pool),只有调用对象的notify()方法(或notifyAll()方法)时才能唤醒等待池中的线程进入等锁池(lockpool),如果线程重新获得对象的锁就可以进入就绪状态
可能不少人对什么是进程,什么是线程还比较模糊,对于为什么需要多线程编程也不是特别理解。
简单的说:
进程是具有一定独立功能的程序关于某个数据集合上的一次运行活动,是操作系统进行资源分配和调度的一个独立单位;
线程是进程的一个实体,是CPU调度和分派的基本单位,是比进程更小的能独立运行的基本单位。线程的划分尺度小于进程,这使得多线程程序的并发性高;进程在执行时通常拥有独立的内存单元,而线程之间可以共享内存。
&&相关文章推荐
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:128225次
积分:2082
积分:2082
排名:第18461名
原创:138篇
转载:14篇
评论:10条
(17)(27)(27)(58)(15)(6)(1)(1)查看 4645回复 0
在线时间0 小时
主题帖子果子
android子线程如何暂停和唤醒?我想在主线程里面做这样的控制
Copyright &.All right reservedAccess denied |
used Cloudflare to restrict access
Please enable cookies.
What happened?
The owner of this website () has banned your access based on your browser's signature (fbbe0d91-ua98).线程的结束,挂起和恢复(下)
线程的结束,挂起和恢复(下)
Author : Aoyousatuo
二. 线程的挂起与恢复
同样, Android线程类也提供了一些公共方法去挂起和恢复线程:
final void () &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
This method is deprecated. Used with deprecated
final void ()
This method is deprecated. May cause
同样不幸的是,通过说明我们可以看到,这些方法Android也是不推荐使用的,经过笔者试验,这些方法也没有效果。那我们如何去挂起和恢复线程呢?笔者又来救赎了。
Android的类基本都是继承于Object类。此类可以说是Android类的祖先了。如果把Android类比喻为一个生物界,则Object类就是当初生命诞生时候的那个单细胞。
我们可以发现Object类提供了几个方法 :
&&&&&&final void ()
Causes a thread which is waiting on this object's
monitor (by means of calling one of the wait() methods) to be woken
final void ()
Causes all threads which are waiting on this
object's monitor (by means of calling one of the wait() methods) to be woken
final void ()
Causes the calling thread to wait until another
thread calls the notify() or notifyAll() method of this object
通过说明我们可以知道,wait方法可以让正在调用的线程处于等待状态,直到其他线程调用了该对象的notify
或者notifyAll,而notify
和notifyAll方法则是用于唤醒处于等待中的线程。
同样,线程类也是继承于Object类,但是线程类是一个比较特殊的类,有自己独立的栈机制来处理其方法,参数和局部变量。通过实验,笔者发现,虽然线程类继承于Object类,但是却不能通过wait和notify方法挂起唤醒线程。而要实现上述动作,必须去间接地实现,即在自定义线程类中创建一个Object对象,然后通过对该Object的相关操作实现线程的挂起和唤醒。方法如下:
在自定义线程类的实例化过程中创建一个Object对象。
定义一个变量来记录线程的状态是否挂起,初始化为假。
在线程类中的run函数中的线程执行部分找入锲点来执行下面动作:如果当前状态变量为假(表示线程挂起),则通过1中Object对象的wait方法挂起当前线程,即线程暂停在锲点位置,如果被唤起,则将从锲点后继续执行。
定义一个方法来修改线程状态变量为真,从而达到挂起线程的目的。
定义一个方法去唤醒线程。判断如果线程状态变量为真,则修改其为假,然后调用1中Object对象的notifyAll方法唤醒对象。(notify方法也可以,但是如果自定义线程较多时容易造成死锁)。
综上,当自定义线程运行后我们可以通过4中的方法挂起线程,通过5中的方法唤醒线程。
程序实例 :
class SearchThread extends Thread
private Object mPauseLock ;
private boolean mPauseFlag ;&&&
public SearchThread()
mPauseLock = new Object() ;
mPauseFlag = false ;
public void onPause()
synchronized (mPauseLock) {
&&&&&&&&&&&&
mPauseFlag = true;
&&&&&&&&&&&&
public void onResume()
synchronized (mPauseLock) {
&&&&&&&&&&&&
mPauseFlag = false ;
&&&&&&&&&&&&
mPauseLock.notifyAll() ;
&&&&&&&&&&&&
&&&&&&&&&&&&
private void pauseThread()
synchronized (mPauseLock) {
&&&&&&&&&&&&
if(mPauseFlag)
&&&&&&&&&&&&
&&&&&&&&&&&&&&&
&&&&&&&&&&&&&&&&&&
mPauseLock.wait() ;
&&&&&&&&&&&&&&&
}catch(Exception e){
&&&&&&&&&&&&&&&&&&
Log.v("thread", "fails") ;
&&&&&&&&&&&&&&&
&&&&&&&&&&&&
&&&&&&&&&&&&
public void run()
//---线程执行部分,仅仅举例为了说明-----
for(int i = 0; i & 100; i++)
pauseThread() ;
for(int j = 0; j & 100; j++)
&&&&&&&&&&&&&&
pauseThread() ;
&&&&&&&&&&&&&&
//-----end----------
好了,大家鼓掌吧。 :)
已投稿到:
以上网友发言只代表其个人观点,不代表新浪网的观点或立场。

我要回帖

更多关于 怎么让线程暂停 的文章

 

随机推荐