java多线程及线程池小结

最近在学习线程池的东西,前面有篇文章《线程池的设计原则》,当然大多都是参考别人的思想。然后发现自己多线程真的写的太少了。现在来补充基础知识咯。。。 

wait导致当前的线程等待,直到其他线程调用此对象的 notify() 方法或 notifyAll() 方法。当前的线程必须拥有此对象监视器。该线程发布对此监视器的所有权并等待,直到其他线程通过调用 notify 方法,或 notifyAll 方法通知在此对象的监视器上等待的线程醒来。然后该线程将等到重新获得对监视器的所有权后才能继续执行.

以上是jdk api的说明,对照说明写个测试:
ContractedBlock.gif ExpandedBlockStart.gif Code
<!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />-->public class Test extends Thread {

    @Override
    
public void run() {
        System.out.println("before wait!");
        
try {
            
synchronized (this) {
                
this.wait();
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        
try {
            Thread.sleep(20000);
        } catch (Exception e) {
            System.out.println("interrupted!");
        }
        System.out.println("after wait!");
    }

    
public synchronized void weakup() {
        
this.notify();
    }
}

public class Main {

    
public static void main(String[] args) {
        Test test = new Test();
        test.start();
        System.out.println("shit");
        
try {
            Thread.sleep(2000);
        } catch (Exception e) {
        }
        test.weakup();
        
try {
            Thread.sleep(2000);
        } catch (Exception e) {
        }
        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的线程池就比较清楚了:
ContractedBlock.gif ExpandedBlockStart.gif Code
<!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />-->class ControlRunnable implements Runnable {
        ThreadPool p;
        Thread t;
        ThreadPoolRunnable toRun;
        
boolean shouldTerminate;
        
boolean shouldRun;
        
boolean noThData;
        Object thData[] = null;

        ControlRunnable(ThreadPool p) {
            toRun = null;
            shouldTerminate = false;
            shouldRun = false;
            
this.p = p;
            t = new Thread(this);
            t.start();
            noThData = true;
            thData = null;
        }

        
public void run() {
            
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 (Throwable t) {
                        System.err.println("ControlRunnable Throwable: ");
                        t.printStackTrace();
                        shouldTerminate = true;
                        shouldRun = false;
                        p.notifyThreadEnd();
                    } finally {
                        
if (shouldRun) {
                            shouldRun = false;
                            p.returnController(this);
                        }
                    }
                    
if (shouldTerminate) {
                        
break;
                    }
                } catch (InterruptedException ie) {
                }
            }
        }

        
public synchronized void runIt(ThreadPoolRunnable toRun) {
            
if (toRun == null) {
                
throw new NullPointerException("No Runnable");
            }
            
this.toRun = toRun;
            shouldRun = true;
            
this.notify();
        }

        
public synchronized void terminate() {
            shouldTerminate = true;
            
this.notify();
        }
ControlRunnable线程类是线程池中的具体线程,线程构造函数中调用线程的start开始线程,到run方法里得到自己的锁然后wait,等待具体的动作调用:runIt,动作调用就可以notify线程了。里边将线程要做的具体工作委托给了ThreadPoolRunnable接口,用户要使用线程池,只用将自己的任务实现此接口即可。ThreadPoolRunnable的代码如下:
<!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--> public   interface  ThreadPoolRunnable {
    
public  Object[] getInitData();
    
        
public   void  runIt(Object thData[]);
}
另外,ThreadPool本身还运行了一个MonitorRunnable的线程,用来管理线程池。当(currentThreadCount - currentThreadsBusy) > maxSpareThreads,就会调用ControlRunnable类的terminate方法删除空闲线程,准备删除的线程是否空闲是通过shouldTerminate参数来判断。线程池采用Vector来存储当前空闲的线程。

接下来回去研究java nio包。网络编程也是自己一直都想去系统的学习的东西。而且,在java nio中有很多和多线程相通的地方。比如非阻塞和多线程,当然,他们不是一个意思。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值