java中怎么判断java 多线程 锁 通知将要死亡(怎么得到死亡通知

问题:java中怎么判断线程将要死亡(怎么得到死亡通知?
描述: & 在java中,怎么判断线程将要死亡或者已经死亡(或者理解为得到java线程死亡通知)?& 网上搜了下,没什么答案,哪位大神能帮我解决下?解决方案1:干嘛一定要用java内置的API来解决这个问题呢,try...finally一下就解决了public class MyRunner implements Runnable {
public void run() {
//TODO:该干啥干啥
System.out.println(&我将在100纳秒内死亡,可不可以抢救下&);
//TODO:发求救信号或者死亡通知
}解决方案2:CyclicBarrier cb = new CyclicBarrier(4, new MainTask());
ExecutorService pool = Executors.newCachedThreadPool();
pool.execute(new ChildTask(cb));
pool.execute(new ChildTask(cb));
pool.execute(new ChildTask(cb));
pool.execute(new ChildTask(cb));
可以用CyclicBarrier,等到4个子线程执行完毕后会调用MainTask()线程。这样相当于获取了4个子线程已经死亡信息解决方案3:创建一个监控线程解决方案4:得线程通知你 应该没法获得解决方案5:异常结束倒是可以解决方案6:楼主是想获取什么吗?如果想获取返回值,可以实现Callable接口,call方法调用之后,会返回一个future&
,不知道偏题没。解决方案7:写一个callback解决方案8:if(thread.getState()!=Thread.State.TERMINATED){}解决方案9:必须判断脑组织是否死亡。解决方案10:线程执行完run方法就死亡了,想知道将要死亡可以在run方法最后通知你线程死亡,死亡后的线程无法得到
以上介绍了“java中怎么判断线程将要死亡(怎么得到死亡通知?”的问题解答,希望对有需要的网友有所帮助。
本文网址链接:/itwd/1198952.html
上一篇: 下一篇:Java线程大全 - 稻草 - ITeye技术网站
博客分类:
1 何为线程
可以把一个线程想象成流水线,多线程就是为了多个流水线同时工作(同时下载多个文件),也可以不把不同的事务分发到不同的流水线上(一边下载到缓存,一边保存缓存保存到磁盘)。
以下载文件为例,
l 单线程下载三个文件如下图,必须文件下载完成后才能下载文件。
l 多线程下载三个文件情况如下图,三个文件同时开始下载。
l 多线程下载一个文件情况如下图,将下载一个文件分为下载线程和保存线程,两个线程以缓冲区作为中介,这是典型的生产者消费者模式。
2 启动和结束线程
2.1 启动线程
中实现线程有两种方法:
2.1.1 ,重写 方法
Thread thread = new Thread("ThreadName")
public void run()
// do something here
thread.start();
上述代码首先创建了继承,并覆盖方法的匿名类。然后创建一名为的线程,线程启动后会执行方法,返回后线程随即销毁。
,实际代码应该根据业务含义取名称,这对查看日志和调试都有很大的用处。
2.1.2 接口,放到中执行
Runnable runnable = new Runnable()
public void run()
// 线程中执行的代码
Thread thread = new Thread(runnable, "ThreadName");
thread.start();
// 启动线程
上述代码首先创建了实现接口的匿名类,然后将匿名类的对象放入中执行。
2.2 结束线程
当方法结束后(或抛出异常)线程随之结束。
· 所有的Java代码都是在某个线程中执行的,所以在任一行Java代码中使用Thread.currentThread()都可以得到当前运行线程。
· JVM允许多个线程并发执行,虽然同一时刻只能有一个线程占用CPU,但每个线程占有的时间片非常短,所以人类的感官上多个线程是并发执行的。
· 当 JVM启动时,至少有一个用户线程运行,即执行某个类的main方法的线程。
2.3 线程生命周期
被调用后,进入CPU而言,CPU
方法结束,。
2.4 守护线程
有一种线程叫守护线程,和普通线程唯一的区别就是在线程启动前调用了线程对象的(true)函数如下面代码示例。
Thread thread = new Thread("ThreadName")
public void run()
// 线程中执行的代码
thread.setDaemon(true);
thread.start();
// 启动线程
如果在线程启动后调用,会抛出异常。
当程序中所有线程都是守护线程时,虚拟机就会退出程序。
3 线程同步 synchronized
在很多系统中都要用到递增的序列,下面是实现代码;我们期望每次返回递增的数字。
public class SequenceMaker
public final static SequenceMaker instance = new SequenceMaker();
private int sequence = 0;
public int nextSequence()
if (sequence == Integer.MAX_VALUE )
sequence = 0;
sequence ++;
然后我们编写测试代码,启动两个线程调用序列生成函数
public class User extends Thread
public void run()
SequenceMaker sequenceMaker = SequenceMaker.
while(true)
int seq = sequenceMaker.nextSequence();
System.out.println(getName() + ": " + seq);
public static void main(String[] args)
User user0 = new User();
User user1 = new User();
user0.setName("user0");
user1.setName("user1");
user0.start();
user1.start();
测试结果:发现有时候返回了相同的数字。
问题在哪里呢?当两个线程按照下面的时序执行时并发生问题。
修改办法就是增加关键字,增加后代码如下:
public synchronized int nextSequence()
增加关键字后保证能够原子执行如果两个线程同时调用一个函数,必须一个先执行,等执行完毕才能另一个线程才能执行该函数。
到这里我们的主角终于出现了。
更一般的形式是:
synchronized (令牌)// 请求令牌,如果不能获得,则阻塞直到获得令牌
需要原子执行的代码
} // 释放令牌
多个线程执行上述代码时,线程首先要获得令牌,才能执行花括号之间的代码。
任何对象都可以是令牌,不同的令牌守护不同的代码,下面的代码每次都产生新的令牌,不能起到同步作用。
public int nextSequence() // 错误的写法
Object lock = new Object();
synchronized (lock)
if (sequence == Integer.MAX_VALUE)
sequence = 0;
sequence++;
正确的写法如下,将令牌放到成员变量。
Object lock = new Object();
public int nextSequence()
synchronized (lock)
if (sequence == Integer.MAX_VALUE)
sequence = 0;
sequence++;
如果要提供两个独立的序列,或返回多个序列的方法,则代码如下
Object lock = new Object();
public int nextSequence()
synchronized (lock)
if (sequence == Integer.MAX_VALUE)
sequence = 0;
sequence++;
和可以并发执行(采用了两个令牌);
和0B不能并发执行的(采用了同一个令牌);
函数声明的又是什么含义呢?
下面的代码中左边和右边是等效的。
4 生产者和消费者
生产者消费者线程如下图,可以有生产者线程和消费者线程。
4.1 生产者-消费者实例
4.1.1 总体设计
总体类图如下:
类是最核心的类,设计成模板类。
4.1.2 向产品队列增加产品
首先看看向产品队列中增加产品的方法。
public void add(P p)
synchronized (products)
// 1 如果队列满了,就等待消费者取走产品
while (products.size() == maxProductCount)
products.wait(); // 线程被阻塞,阻塞期间锁被释放
catch (InterruptedException e)
// 2 将产品放入队列
products.add(p);
// 3 唤醒其它线程:等待的消费者去取
products.notifyAll();
这里出现了两个新的函数,令牌对象的 wait() 和 notifyAll();这两个方法来之类,中这样描述:
notifyAll()
Wakes up all threads that are waiting on this object's monitor.
Causes current thread to wait until another thread invokes the
method or the
method for this object.
相关的函数还有:、、
Wakes up a single thread that is waiting on this object's monitor.
wait(long timeout)
Causes current thread to wait until either another thread invokes the
method or the
method for this object, or a specified amount of time has elapsed.
wait(long timeout, int nanos)
Causes current thread to wait until another thread invokes the
method or the
method for this object, or some other thread interrupts the current thread, or a certain amount of real time has elapsed.
Tip:和的主要区别,
sleep() 一段时间,不会释放锁;
;所以方法必须在范围内调用。
其中第一步判断队列是否已满,如果满了就等待消费者取走产品。注意这里用了一个循环判断,而不是。中这样描述原因:
l 另一个线程可能得到了锁,并且在一个线程中调用的时刻,到等待线程醒过来的时刻之间,得到锁的线程已经改变了被保护的状态。
l 条件并没有成立,但是另一个线程可能意外地或恶意地调用了。在公有可访问的对象上等待,这些类实际上把自己暴露在危险的境地中。在一个公有可访问对象的同步方法中包含的都会出现这样的问题。
l 通知线程在唤醒等待线程时可能会过度“大方”。例如,即使只有莫一些等待线程的条件已经满足,但是通知线程仍必须调用。
l 在没有通知的情况先等待线程也可能会醒来。这被称为“伪唤醒()”。虽然《》并米有提到这种可能性,但是许多实现都使用了具有伪唤醒功能的线程设施,尽管用得很少。
4.1.3 从产品队列取出产品
有了上面的知识,消费者线程从产品队列中获取产品的方法就容易实现了。
public P take()
synchronized (products)
// 1 如果队列为空,就等待生产者放入产品
while (products.size() == 0)
products.wait(); // 线程被阻塞
catch (InterruptedException e)
// 2 将产品从队列中取走
p = products.remove(0);
// 3 唤醒其它线程:等待的生产者放入产品
products.notifyAll();
4.1.4 生产者和消费者
生产者代码:
public void run()
int count = 100;
while (!productQueue.isDisposed())
productQueue.add(SequenceMaker.instance.nextSequence());
if (count == 0)
消费者代码:
public void run()
while (!productQueue.isDisposed())
Integer p = productQueue.take();
System.out.println(getName() + " take: " + p);
4.1.5 main函数代码
public static void main(String[] args) throws InterruptedException
PropertyConfigurator.configure("trace.log");
ProductQueue&Integer& productQueue = new ProductQueue&Integer&(10);
Producer producer0 = new Producer(productQueue);
Producer producer1 = new Producer(productQueue);
producer0.setName("producer0");
producer1.setName("producer1");
Consumer consumer0 = new Consumer(productQueue);
Consumer consumer1 = new Consumer(productQueue);
consumer0.setName("consumer0");
consumer1.setName("consumer1");
producer0.start();
producer1.start();
consumer0.start();
consumer1.start();
// 等待生产者结束
producer0.join();
producer1.join();
// 结束消费者
productQueue.dispose();
4.2 JDK本身对生产者-消费者的支持
接口:,实现类:、等。
5 异步转为同步
在网络编程中,有发送线程和结束线程,查询数据为例,流程如下:
上图可以看出,查询数据的流程被分割到两个线程,代码的可读性、可维护性都有很差。
利用上面学习到的生产者和消费者的知识,我们可以把业务放到一个流程中。
6 Swing线程
6.1 Swing线程基础
Swing最关键的线程就是事件派发线程
l 将事件(键盘、鼠标)派发到各个组件,并负责调用绘制方法更新界面。
l 按钮的事件响应方法actionPerformed并是在EDT中执行的。
l 如果在EDT线程中执行费时的操作,如查询数据库、写文件,就会导致界面卡住;如果不小心发生死锁还会导致界面一片空白。
组件被显示
违反了上面的规则,如我们在其它线程中对界面做操作更新按钮文字、增加树节点等就会出现同步问题,典型的现象有:界面显示错乱。
6.2 invokeLater和invokeAndWait
如何避免上面的异常呢,提供了两个函数:
Runnable doRun = new Runnable() // 1 创建Runnable对象
public void run()
frame.setTitle("xxxx");
SwingUtilities.invokeLater(doRun); // 2 将Runnable对象放到EDT中执行
那么和有和区别呢?
l 和都是。
l 方法才返回。
invokeLater的时序图,业务调用后,继续执行代码:
invokeAndWait的时序图,业务调用后,必须等方法在中执行后才能继续执行:
浏览: 45517 次
来自: 杭州
NIO是需要移除监听key的吧
否则一直都会返回TRUE
貌似不注册写,也可以任意写。
高,这是在是高
LZ的广告展示数量好高,可惜ecpm低了点,不然收入能上一个数 ...
试试HTML5的canvas吧,现成的可以用Flot:http ...JAVA里面如何让一个线程死亡或结束(1)
  这问题也是很常见的问题,自打 stop不推荐使用后,我们还有别的可以选择的方法吗?
  设置一个标志,让其自动return最安全。
  * JAVA里面如何使用一个线程死亡或结束.
  public class T {
  public static void main(String[] args) {
  // 启动线程
  MyThread thread = new MyThread();
  new Thread(thread).start();
  // 你的其它的工作,此时线程在运行中
  // 你不想让线程干活了,停掉它
  // 注意,这只是一个标志,具体线程何时停,并不能精确控制
  thread.allDone =
本文标题: 本文地址:
一周人气榜java线程|LOFTER(乐乎) - 让兴趣,更有趣
LOFTER for ipad —— 让兴趣,更有趣
下载移动端
关注最新消息
&nbsp&nbsp被喜欢
&nbsp&nbsp被喜欢
{list posts as post}
{if post.type==1 || post.type == 5}
{if !!post.title}${post.title|escape}{/if}
{if !!post.digest}${post.digest}{/if}
{if post.type==2}
{if post.type == 3}
{if !!post.image}
{if post.type == 4}
{if !!post.image}
{if !!photo.labels && photo.labels.length>0}
{var wrapwidth = photo.ow < 500?photo.ow:500}
{list photo.labels as labs}
{var lbtxtwidth = Math.floor(wrapwidth*(labs.ort==1?labs.x:(100-labs.x))/100)-62}
{if lbtxtwidth>12}
{if !!labs.icon}
{list photos as photo}
{if photo_index==0}{break}{/if}
品牌${make||'-'}
型号${model||'-'}
焦距${focalLength||'-'}
光圈${apertureValue||'-'}
快门速度${exposureTime||'-'}
ISO${isoSpeedRatings||'-'}
曝光补偿${exposureBiasValue||'-'}
镜头${lens||'-'}
{if data.msgRank == 1}{/if}
{if data.askSetting == 1}{/if}
{if defined('posts')&&posts.length>0}
{list posts as post}
{if post_index < 3}
{if post.type == 1 || post.type == 5}
{if !!post.title}${post.title|escape}{/if}
{if !!post.digest}${post.digest}{/if}
{if post.type == 2}
{if post.type == 3}
{if post.type == 4}
{if post.type == 6}
{if drlist.length>0}
更多相似达人:
{list drlist as dr}{if drlist.length === 3 && dr_index === 0}、{/if}{if drlist.length === 3 && dr_index === 1}、{/if}{if drlist.length === 2 && dr_index === 0}、{/if}{/list}
暂无相似达人,
{if defined('posts')&&posts.length>0}
{list posts as post}
{if post.type == 2}
{if post.type == 3}
{if post.type == 4}
{if post.type == 6}
this.p={ currentPage:1,pageNewMode:true,isgooglead3:false,ishotrecompost:false,visitorId:0, first:'',tag:'java线程',recommType:'new',recommenderRole:0,offset:10,type:0,isUserEditor:0,};}

我要回帖

更多关于 java子线程通知主线程 的文章

更多推荐

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

点击添加站长微信