java多线程及线程池小结-atomti-iteye技术网站

本文详细介绍了Java中多线程的基础知识及线程池的应用原理。重点讲解了wait与notify方法的工作机制,以及中断(interrupt)在多线程中的作用。通过具体的代码示例展示了线程池的具体实现方式。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

java多线程及线程池小结-atomti-iteye技术网站
2011年08月01日
  最近在学习线程池的东西,前面有篇文章《线程池的设计原则》,当然大多都是参考别人的思想。然后发现自己多线程真的写的太少了。现在来补充基础知识咯。。。
  wait导致当前的线程等待,直到其他线程调用此对象的 notify() 方法或 notifyAll() 方法。当前的线程必须拥有此对象监视器。该线程发布对此监视器的所有权并等待,直到其他线程通过调用 notify 方法,或 notifyAll 方法通知在此对象的监视器上等待的线程醒来。然后该线程将等到重新获得对监视器的所有权后才能继续执行. publicclassTestextendsThread{
  @Override
  publicvoidrun(){
  System.out.println("beforewait!");
  try{
  synchronized(this){
  this.wait();
  }
  }catch(InterruptedExceptione){
  e.printStackTrace();
  }
  try{
  Thread.sleep(20000);
  }catch(Exceptione){
  System.out.println("interrupted!");
  }
  System.out.println("afterwait!");
  }
  publicsynchronizedvoidweakup(){
  this.notify();
  }
  }
  publicclassMain{
  publicstaticvoidmain(String[]args){
  Testtest=newTest();
  test.start();
  System.out.println("shit");
  try{
  Thread.sleep(2000);
  }catch(Exceptione){
  }
  test.weakup();
  try{
  Thread.sleep(2000);
  }catch(Exceptione){
  }
  test.interrupt();
  System.out.println("shit");
  }
  wait和notify针对的是对象,而不是线程。因为这两个方法都是Object的方法。与线程无关。
  所有的线程结束之后,程序才会结束。此处如果不sleep的话,有可能weakup会早于wait先调用。
  执行interrupt()时,并不需要获取Thread实例的锁定.任何线程在任何时刻,都可以调用其他线程interrupt().当sleep中的线程被调用interrupt()时,就会放弃暂停的状态.并抛出InterruptedException.
  interrupt()不会中断一个正在运行的线程。这一方法实际上完成的是,在线程受到阻塞时抛出一个中断信号,这样线程就得以退出阻塞的状态。更确切的说,如果线程被Object.wait, Thread.join和Thread.sleep三种方法之一阻塞,那么,它将接收到一个中断异常(InterruptedException),从而提早地终结被阻塞状态。
  如果线程没有被阻塞,这时调用interrupt()将不起作用;否则,线程就将得到异常(该线程必须事先预备好处理此状况),接着逃离阻塞状态。
  线程A在执行sleep,wait,join时,线程B调用A的interrupt方法,的确这一个时候A会有InterruptedException异常抛出来.但这其实是在sleep,wait,join这些方法内部会不断检查中断状态的值,而自己抛出的InterruptedException。
  如果线程A正在执行一些指定的操作时如赋值,for,while,if,调用方法等,都不会去检查中断状态,所以线程A不会抛出InterruptedException,而会一直执行着自己的操作.当线程A终于执行到wait(),sleep(),join()时,才马上会抛出InterruptedException.
  若没有调用sleep(),wait(),join()这些方法,或是没有在线程里自己检查中断状态自己抛出InterruptedException的话,那
  InterruptedException是不会被抛出来的.
  下面再看tomcat的线程池就比较清楚了:
  classControlRunnableimplementsRunnable{
  ThreadPoolp;
  Threadt;
  ThreadPoolRunnabletoRun;
  booleanshouldTerminate;
  booleanshouldRun;
  booleannoThData;
  ObjectthData[]=null;
  ControlRunnable(ThreadPoolp){
  toRun=null;
  shouldTerminate=false;
  shouldRun=false;
  this.p=p;
  t=newThread(this);
  t.start();
  noThData=true;
  thData=null;
  }
  publicvoidrun(){
  while(true){
  try{
  synchronized(this){
  if(!shouldRun&&!shouldTerminate){
  this.wait();
  }
  }
  if(shouldTerminate){
  break;
  }
  try{
  if(noThData){
  thData=toRun.getInitData();
  noThData=false;
  }
  if(shouldRun){
  toRun.runIt(thData);
  }
  }catch(Throwablet){
  System.err.println("ControlRunnableThrowable:");
  t.printStackTrace();
  shouldTerminate=true;
  shouldRun=false;
  p.notifyThreadEnd();
  }finally{
  if(shouldRun){
  shouldRun=false;
  p.returnController(this);
  }
  }
  if(shouldTerminate){
  break;
  }
  }catch(InterruptedExceptionie){
  }
  }
  }
  publicsynchronizedvoidrunIt(ThreadPoolRunnabletoRun){
  if(toRun==null){
  thrownewNullPointerException("NoRunnable");
  }
  this.toRun=toRun;
  shouldRun=true;
  this.notify();
  }
  publicsynchronizedvoidterminate(){
  shouldTerminate=true;
  this.notify();
  }
  ControlRunnable线程类是线程池中的具体线程,线程构造函数中调用线程的start开始线程,到run方法里得到自己的锁然后wait,等待具体的动作调用:runIt,动作调用就可以notify线程了。里边将线程要做的具体工作委托给了ThreadPoolRunnable接口,用户要使用线程池,只用将自己的任务实现此接口即可。ThreadPoolRunnable的代码如下:
  另外,ThreadPool本身还运行了一个MonitorRunnable的线程,用来管理线程池。当(currentThreadCount - currentThreadsBusy) > maxSpareThreads,就会调用ControlRunnable类的terminate方法删除空闲线程,准备删除的线程是否空闲是通过shouldTerminate参数来判断。线程池采用Vector来存储当前空闲的线程。
  接下来回去研究java nio包。网络编程也是自己一直都想去系统的学习的东西。而且,在java nio中有很多和多线程相通的地方。比如非阻塞和多线程,当然,他们不是一个意思。
  
  
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值