在android 怎样唤醒 处于阻塞 状态的线程挂起和阻塞和等待

2363人阅读
Android(25)
Android 线程处理
热1已有 301 次阅读&
17:29 & :& &
1.多线程的两种实现方式:
join().等待当前线程执行完毕后,才允许为其他线程的执行,如果此线程中断产生InterruptedException异常。 yield().让此线程暂停执行,先让其他线程执行 start(),run(),setPriority()...
只需实现run(),但没有启动线程的start()方法,因此需要使用Thread类
2.线程安全:线程同步synchronized。可以用作线程方法和线程块。
synchronized(this){
&&&code...
3.多线程的互动处理wait()和notify()
notify()只会唤醒同一个对象但处于wait()状态的线程。 这两个方法定义在Object类中,任何对象都可以使用,但必须在synchronized域中才可以调用,否则illegalMonitorStateException异常。
避免相互等待-死锁
4.线程通信。
UI线程(管理用户界面的线程)是不安全的,不要阻塞ui线程、确保只在ui线程中访问ui组件也就是说只能在UI线程中修改UI组件,不应出现在后台线程中修改的UI组件的情况。比较耗时的工作最好在后台进行,否则可能阻塞UI界面
主要有两种方式:
handler.通过显式的抛出和捕获消息,与UI进行交互。
Message. Message保存了后台返回的数据,可以存储bundle等数据形式。 messageQueue是线程对应looper的一部分,负责存储从后台进程中抛回的和当前handler绑定的message,是一个队列。
实现handleMessage() obtainMessage()获取Message对象 sendMessage()
Activity.runOnUiThread(Runnable) View.post(Runnable) View.postDelayed(Runnable, long)
AsyncTask - AsyncTask&Params, Progress, Result&
Params 启动任务执行的输入参数,比如HTTP请求的URL,Progress 后台任务执行的百分比。Result 后台执行任务最终返回的结果,比如String
doInbackground().在后台线程中运行。 onPostExcute(void result).UI线程中运行 onProgressUpdate().doInBackground中调用了publishProgress之后,ui线程调用该方法,动态的改变进度条。
GetCSDNLogoTask extends
AsyncTask&String, Integer, Bitmap&{
&&&&&&&&@Override
&&&&&&&&protected
Bitmap doInBackground(String... url) {
&&&&&&&&&&&&
&&&&&&&&&&&&publishProgress(0);
&&&&&&&&&&&&HttpClient client =new
DefaultHttpClient();
&&&&&&&&&&&&publishProgress(30);
&&&&&&&&&&&&Log.i(&log_out&, url[0]);
&&&&&&&&&&&&HttpGet get=new
HttpGet(url[0]);
&&&&&&&&&&&&final
&&&&&&&&&&&&try
&&&&&&&&&&&&&&&&HttpResponse response =client.execute(get);
&&&&&&&&&&&&&&&&bt=BitmapFactory.decodeStream(response.getEntity().getContent());
&&&&&&&&&&&&}
catch (ClientProtocolException e) {
&&&&&&&&&&&&&&&&return
&&&&&&&&&&&&}
catch (IOException e) {
&&&&&&&&&&&&&&&&return
&&&&&&&&&&&&}
&&&&&&&&&&&&publishProgress(100);
&&&&&&&&&&&&return
&&&&&&&&@Override
&&&&&&&&protected
void onCancelled() {
&&&&&&&&&&&&progressBar.setProgress(0);
&&&&&&&&@Override
&&&&&&&&protected
void onCancelled(Bitmap result) {
&&&&&&&&&&&&progressBar.setProgress(0);
&&&&&&&&@Override
&&&&&&&&protected
void onPostExecute(Bitmap result) {
&&&&&&&&&&&&if(result !=
&&&&&&&&&&&&&&&&Toast.makeText(AsyncTaskActivity.this,
&success to get the logo...&, Toast.LENGTH_LONG).show();
&&&&&&&&&&&&&&&&imgView.setImageBitmap(result);
&&&&&&&&&&&&&&&&Log.i(&Log_out&,&img setting...&);
&&&&&&&&&&&&}else
&&&&&&&&&&&&&&&&Toast.makeText(AsyncTaskActivity.this,
&failed...&, Toast.LENGTH_LONG).show();
&&&&&&&&&&&&}
&&&&&&&&@Override
&&&&&&&&protected
void onPreExecute() {
&&&&&&&&&&&&imgView.setImageBitmap(null);
&&&&&&&&&&&&progressBar.setProgress(0);&&&&&
&&&&&&&&@Override
&&&&&&&&protected
void onProgressUpdate(Integer... progress) {
&&&&&&&&&&&&progressBar.setProgress(progress[0]);
&&&&&&&&}&&&
参考知识库
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:212250次
积分:2467
积分:2467
排名:第11937名
原创:14篇
转载:214篇
评论:14条
(1)(4)(4)(41)(67)(115)Java线程唤醒与阻塞
时间: 19:29:32
阻塞指的是暂停一个线程的执行以等待某个条件发生(如某资源),学过操作系统的同学对它一
定已经很熟悉了。Java 提供了大量方法来支持阻塞,下面让我们分析。
  1. sleep() 方法:sleep() 允许 指定以毫秒为单位的一段时间作为参数,它使得线程在指定的时间
内进入阻塞状态,不能得到CPU 时间,指定的时间一过,线程重新进入可执行状态。
  典型地,sleep() 被用在等待某个资源就绪的情形:测试发现条件不满足后,让线程阻塞一段时间后
重新测试,直到条件满足为止。
  2. suspend() 和 resume() 方法:两个方法配套使用,suspend()使得线程进入阻塞状态,并且不会
自动恢复,必须其对应的resume() 被调用,才能使得线程重新进入可执行状态。典型地,suspend() 和
resume() 被用在等待另一个线程产生的结果的情形:测试发现结果还没有产生后,让线程阻塞,另一个
线程产生了结果后,调用 resume() 使其恢复。
  3. yield() 方法:yield() 使得线程放弃当前的 CPU 时间,但是不使线程阻塞,即线程仍处于
可执行状态,随时可能再次分得 CPU 时间。调用 yield() 的效果等价于调度程序认为该线程已执行了足
够的时间从而转到另一个线程。
  4. wait() 和 notify() 方法:两个方法配套使用,wait() 使得线程进入阻塞状态,它有两种形式
,一种允许指定以毫秒为单位的一段时间作为参数,另一种没有参数,前者当对应的 notify() 被调用或
者超出指定时间时线程重新进入可执行状态,后者则必须对应的 notify() 被调用。
  初看起来它们与 suspend() 和 resume() 方法对没有什么分别,但是事实上它们是截然不同的。区
别的核心在于,前面的所有方法,阻塞时都不会释放占用的锁(如果占用了的话),而这一对方法则
相反。
  上述的核心区别导致了一系列的细节上的区别。
  首先,前面叙述的所有方法都隶属于 Thread 类,但是这一对却直接隶属于 Object 类,也就是说,
所有对象都拥有这一对方法。初看起来这十分不可思议,但是实际上却是很自然的,因为这一对方法阻塞
时要释放占用的锁,而锁是任何对象都具有的,调用任意对象的 wait() 方法导致线程阻塞,并且该对象
上的锁被释放。而调用 任意对象的notify()方法则导致因调用该对象的 wait() 方法而阻塞的线程中随
机选择的一个阻塞(但要等到获得锁后才真正可执行)。
  其次,前面叙述的所有方法都可在任何位置调用,但是这一对方法却必须在 synchronized 方法或块
中调用,理由也很简单,只有在synchronized 方法或块中当程才占有锁,才有锁可以释放。同样的
道理,调用这一对方法的对象上的锁必须为当前线程所拥有,这样才有锁可以释放。因此,这一对方法调
用必须放置在这样的 synchronized 方法或块中,该方法或块的上锁对象就是调用这一对方法的对象。若
不满足这一条件,则程序虽然仍能编译,但在运行时会出现 IllegalMonitorStateException 异常。
  wait() 和 notify() 方法的上述特性决定了它们经常和synchronized 方法或块一起使用,将它们和
操作系统的进程间通信机制作一个比较就会发现它们的相似性:synchronized方法或块提供了类似于操作
系统原语的功能,它们的执行不会受到多线程机制的干扰,而这一对方法则相当于 block 和wakeup 原语
(这一对方法均声明为 synchronized)。它们的结合使得我们可以实现操作系统上一系列的进程间
通信的算法(如信号量算法),并用于解决各种复杂的线程间通信问题。
  关于 wait() 和 notify() 方法最后再说明两点:
  第一:调用 notify() 方法导致解除阻塞的线程是从因调用该对象的 wait() 方法而阻塞的线程中随
机选取的,我们无法哪一个线程将会被选择,所以编程时要特别小心,避免因这种不确定性而产生问
题。
  第二:除了 notify(),还有一个方法 notifyAll() 也可起到类似作用,唯一的区别在于,调用notifyAll() 方法将把因调用该对象的 wait() 方法而阻塞的所有线程一次性全部解除阻塞。当然,只有获得锁的那一个线程才能进入可执行状态。如果你真的想学习java你可以来这个群前面是五,中间是四一三后面是一四四,这里有技术大牛亲自指导帮助你 还有免费的直播课程学习,谈到阻塞,就不能不谈一谈死锁,略一分析就能发现,suspend() 方法和不指定超时期限的 wait() 方法的调用都可能产锁。遗憾的是,Java 并不在语言级别上支持死锁的避免,我们在编程中必须小心地避免死锁。
  以上我们对 Java 中实现线程阻塞的各种方法作了一番分析,我们重点分析了 wait() 和 notify()
方法,因为它们的功能最强大,使用也最灵活,但是这也导致了它们的效率较低,较容易出错。实际使用
中我们应该灵活使用各种方法,以便更好地达到我们的目的。
总结:
wait和notify、notifyall方法属于Object类,它们涉及到锁的释放问题,所以和synchronized关键字一起使用。
suspend() 和 resume() 方法配套使用。
$T.total > 0 && $T.page <= $T.pageNum}
{#foreach $T.data as r}
{$T.r.formt_tm}{#if $T.r.nickname}{#else}匿名{#/if}
{$T.r.content}
{#if $T.page > 1 && $T.pageNum > 1)
$T.s_num > 2}
{#for index = $T.s_num to $T.e_num}
$T.pageNum > $T.pageNavSize+ 2 && $T.s_num != $T.pageNum - $T.pageNavSize}
{#if $T.pageNum > 1}
{#if $T.pageNum != $T.page && $T.pageNum > 1}
<a href="javascript:void(0);" page="{$T.page 下一页
您的回应...
也许你感兴趣
(C)2012 本站提供的内容来源于广大网络用户,我们不保证内容的正确性。如果转载了您的内容,希望删除的请联系我们!Android中线程和Handle_Linux编程_Linux公社-Linux系统门户网站
你好,游客
Android中线程和Handle
来源:Linux社区&
作者:a_mean
相信大家对线程应该不会太陌生了,线程是进程中的实体,它的生命周期:1.新建 2.就绪 3.运行 4.阻塞 5.死亡。
当我们编写的的UI程序运行后,系统创建了一个叫做“main”的线程,我们可以通过Debug模式进行观看:
这个Main线程也就是主线程,它在Android系统中也叫UI线程。
它负责分发事件给构件,包括绘制事件。例如,当你触摸屏幕上的一个按钮时,UI线程会分发一个触摸事件给构件,
然后,构件会设定自己为被按下的状态,并抛出一个请求给事件队列,UI线程队列接收请求并通知构件绘制自己。
它是非UI安全的,也就是说,不接受非UI线程的修改请求。当我们通过别的线程(非主线程或者说是非原始线程)来修改它的时候,
会抛出这个异常:android.view.ViewRoot$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.
CalledFromWrongThreadException 这个字面上都理解过来了,是说这个请求来自于错误的线程。
Only the original thread that created a view hierarchy can touch its views&只有最初创建视图层次结构的线程才可以接触到这些视图。
也就是说android中相关的view和控件不是线程安全的,我们可以采用以下几种方式:
Activity.runOnUiThread(Runnable)View.post(Runnable)View.postDelayed(Runnable, long)HandlerAsyncTask
其中我认为最简单的而且最没用的就是runOnUiThread了,只要给它一个Runnable,它轻轻松松就运行在UIThread了。但就是因为这个轻轻松松,我们的问题也来了。
因为它是运行在UI线程,也就是给用户展示和操作的线程,我们用它去执行一些操作的话,这个线程就会进入一个阻塞的状态,如果阻塞状态超过5秒的话,系统就
会过来提示你了,这样给用户的体验很不好,如下图:
这时我们就需要用到上面介绍的另外几种方式来处理,这里介绍下一最常用的Handler。
Handler的使用场合:
1&安排messages和runnables在将来的某个时间点执行。
2&将action入队以备在一个不同的线程中执行。即可以实现线程间通信。
& &比如当你创建子线程时,你可以在你的子线程中拿到父线程中创建的Handler对象,就可以通过该对象向父线程的消息队列发送消息了。
& &由于Android要求在UI线程中更新界面,因此,可以通过该方法在其它线程中更新界面。
下面是完整代码,你可以直接跳过看我后面的断点调试。
package&com.&&
import&android.app.A&&
import&android.os.B&&
import&android.os.H&&
import&android.os.M&&
import&android.widget.ProgressB&&
import&android.widget.TextV&&
public&class&AutoActivity&extends&Activity{&&
&&&&private&ProgressBar&&&
&&&&private&TextView&textV&&
&&&&private&MyHandler&myH&&
&&&&@Override&&
&&&&protected&void&onCreate(Bundle&savedInstanceState)&{&&
&&&&&&&&super.onCreate(savedInstanceState);&&
&&&&&&&&setContentView(R.layout.loading);&&
&&&&&&&&&&
&&&&&&&&myHandler=new&MyHandler();&&
&&&&&&&&bar=(ProgressBar)findViewById(R.id.progressBar);&&
&&&&&&&&textView=(TextView)findViewById(R.id.textView);&&
&&&&&&&&&&
&&&&&&&&new&Thread(new&MyThread()).start();&&
&&&&class&MyThread&implements&Runnable{&&
&&&&&&&&@Override&&
&&&&&&&&public&void&run()&{&&
&&&&&&&&&&&&while(bar.getProgress()&bar.getMax()){&&
&&&&&&&&&&&&&&&&Message&msg=new&Message();&&
&&&&&&&&&&&&&&&&&&
&&&&&&&&&&&&&&&&myHandler.sendMessage(msg);&&
&&&&&&&&&&&&&&&&&&
&&&&&&&&&&&&&&&&try&{&&
&&&&&&&&&&&&&&&&&&&&&&
&&&&&&&&&&&&&&&&&&&&Thread.sleep(<FONT color=#c);&&
&&&&&&&&&&&&&&&&}&catch&(InterruptedException&e)&{&&
&&&&&&&&&&&&&&&&&&&&&&
&&&&&&&&&&&&&&&&&&&&e.printStackTrace();&&
&&&&&&&&&&&&&&&&}&&
&&&&&&&&&&&&}&&
&&&&&&&&&&&&System.out.println("used&for&breakPoint");&&
&&&&&&&&}&&
&&&&&&&&&&
&&&&class&MyHandler&extends&Handler{&&
&&&&&&&&@Override&&
&&&&&&&&public&void&handleMessage(Message&msg)&{&&
&&&&&&&&&&&&int&progress=bar.getProgress()+10;&&
&&&&&&&&&&&&bar.setProgress(progress);&&
&&&&&&&&&&&&textView.setText(String.valueOf(progress));&&
&&&&&&&&&&&&super.handleMessage(msg);&&
&&&&&&&&}&&
&&&&&&&&&&
}&&在new Thread(new MyThread()).start();//新建一个子线程并运行 这里,我加入了一个断点。运行完这条语句后,可以清楚地看到我们的虚拟机里确实是多了一个线程:
这时这个线程的状态变化是:1.新建 2.就绪 3.运行。
然后我们在子线程中找到父线程中创建的Handler对象myHandler,然后向它发送一个Message,在这个Message中,可以传递任意我们想传递的数据,
这里我没有什么好传的,所以直接new了一个过去。然后myHandler接到这个Message,进入handleMessage方法,在方法里我对ProgressBar的进度每次加10,
并把它显示在TextView上,我们可以很明显地看到TextView的变化,说明UI线程并没有处于阻塞状态,界面也没有假死。最后ProgressBar的进度到了100%,
也就到了这条语句System.out.println("used for breakPoint");当该语句没有执行时,刚才新建的线程是还存在的,当该语句结束后,也就是该线程的run方法结束后,
这个线程的任务也就完成了,这时它即将进行第5个状态-死亡。但它不是立即死亡,它将作为一个小垃圾被系统回收。当系统执行完执行相关的内存释放操作后,
这个线程就自动结束了,我们可以在Debug中看到虚拟机已经找不到这个进程了
,至此该线程死亡。
我通过线程的生命周期来讲解了一下Handle的用法,如果你认为我表达的意思中有错误的观点或者有任何疑问,都欢迎给我留言,谢谢指点。
相关资讯 & & &
& (03/23/:55)
& (02/17/:44)
& (02/17/:53)
& (02/17/:45)
& (02/17/:52)
& (02/17/:45)
   同意评论声明
   发表
尊重网上道德,遵守中华人民共和国的各项有关法律法规
承担一切因您的行为而直接或间接导致的民事或刑事法律责任
本站管理人员有权保留或删除其管辖留言中的任意内容
本站有权在网站内转载或引用您的评论
参与本评论即表明您已经阅读并接受上述条款}

我要回帖

更多关于 系统一直处于唤醒状态 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信