`
zzhonghe
  • 浏览: 243361 次
  • 性别: Icon_minigender_1
  • 来自: 深圳
社区版块
存档分类
最新评论

Java并发整理笔记

    博客分类:
  • Java
阅读更多
前面对并发编程,我一直是心怀崇敬,如履薄冰。尽管如此,稍微复杂一点的并发任务,就搞的焦头烂额。现整理一些学习笔记,以便随时记录,随时巩固。


 
  
    //该线程池是个可以回收利用的线程池,按需产生线程,可以被复用,线程可以闲置60秒,或者被销毁
    //一般多线程程序,首选该线程池
    public static void testCachedThreadPool(){
        ExecutorService se=Executors.newCachedThreadPool();
        for(int i=0;i<4;i++){
            se.execute(new LiftOff());
        }
        //shutdown的作用是避免提交更多的线程任务
        se.shutdown();
    }
    
    //该线程池产生固定个数的线程,并复用,不被销毁。
    //好处是线程个数有限,即便是糟糕的程序也不能滥用资源
  public static void testFixedCacheThreadPool(){
        ExecutorService se=Executors.newFixedThreadPool(2);
        se.execute(new LiftOff());
        for(int i=0;i<4;i++){
            se.execute(new LiftOff());
        }
    }
    

    
    /**
     * 1.该线程池只产生一个不停止的线程,每次调用线程任务都会等待上一次的任务完成
     * 比如写日志的模块,为了避免主程序等待IO操作,可以传入一个ExecutorService,写日志的时候就向这个线程池
     * 的队列添加一个日志任务
     * 
     * 2.监听socket的任务,比如发送短信。短信的网关只有1个Socket出口,也就是同时只能发1条信息。但是界面提交信息数可能
     * 在某一时间大量任务,那么这时候可以采用这个线程池,让所有的任务进行排队。而不是在socket出口上对资源进行锁定。
     * 避免了在资源同步上繁琐的处理。
     * 
     * 3.事件分发线程,响应事件的时候,采用同一接口分发事件。各个时间按照抛出的先后顺序排队,然后按次序分发
     * 
     * 某种意义上讲,这是一个单队列任务,大量线程任务使用同一资源时很有效
     */
    public static void testSingleThreadExecutor(){
        ExecutorService se=Executors.newSingleThreadExecutor();
        for(int i=0;i<4;i++){
            se.execute(new LiftOff());
        }
    }
    
    /**
     * 1.Callable返回的值可以是任意类型
     * 2.采用ExecutorService.submit方法来执行
     * 3.Callable的Cancel必须在还未调用get方法的时候调用,不然cancel不了。
     * 4.isDone方法可以判断是否有返回结果了
     * 5.get方法是个同步的方法,会一直等待返回结果,然后退出
     */
    public static void testCallableThread(){
        ExecutorService se=Executors.newCachedThreadPool();
        Future<Integer> f1=se.submit(new LiftOffCallable());
        //f1.cancel(true);
        System.out.println(f1.isCancelled());
        System.out.println(f1.isDone());
        try {
            //System.out.println(f1.get());
            System.out.println(f1.isDone());
            System.out.println(f1.isCancelled());
            f1.cancel(true);
            System.out.println(f1.isCancelled());
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        se.shutdown();
    }
    
    /**
     * sleep与yield的相同点在于, 都会让当前线程放弃cpu,让其他线程执行。
     * sleep在指定的时间后才能执行, yield则不预见什么时候能执行
     * 
     * sleep的机制在不同的平台实现有所不一样,尽量不要用。很多情况下,可以采用wait,或者yield来实现类似功能:
     * 1.比如不断查询某个结果是否有值
     * 2...
     * 
     * wait不能和这2个混淆,不能因为名字也一样短,就认为有什么共同点
     * 
     * TimeUnit提供了操作线程状态的几个简略方法: TimeUnit.MILLISECONDS.
     */
    public void testSleep(){
        while(true){
            try {
                TimeUnit.MILLISECONDS.timedJoin(new Thread(), 110l);
                TimeUnit.MILLISECONDS.timedWait(new Object(), 110l);
                TimeUnit.MILLISECONDS.sleep(10l);
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    }
    
    /*
     * 通常情况,操纵优先级都是一种错误
     * 应该在run方法的开始部分设置,构造器里面设置没有什么好处
     * JDK有10个优先级,真正所有系统都支持的只有3个,MAX,MIN,NORM
     * 
     * volatile定义的变量,不能进行任何编译器优化
     */
    public void testThreadPriority(){
        Thread.currentThread().setPriority(1);
    }
    
    /*
     * yield能够促使各种不同的任务之间,产生良好的处理机制,除此之外,不能作其他用处
     * 
     * 需要注意的,我们的程序逻辑,不能依赖这个机制
     */
    public void testYield(){
        Thread.yield();
    }
    
    /*
     * Daemon是后台线程,只要还有非后台线程存在,那么Daemon就不会停止
     * Daemon提供的是通用服务线程,但它不是必不可少的部分
     * 
     * 
     * Daemon线程是为其他线程服务的,并不是程序的本地,比如说垃圾回收机制,当所有的线程都
     * 运行完毕,垃圾回收Daemon才会停止。
     * 
     * 比如在main里面创建一系列后台线程,当main结束时候,所有后台线程也结束了
     * 
     * 不要再构造方法里面启动线程,这样有可能构造还没有结束就开始线程了,所以总是用Executor.execute来执行线程
     */
    public void testDaemon(){
        new Daemon();
    }
    
    /*
     * 创建同种特性的线程,可以只用ThreadFactory定义一次
     * 比如,创建一批Daemon线程,都拥有最大的priority
     */
    public void testThreadFactory(){
        ExecutorService se=Executors.newSingleThreadExecutor(new ThreadFactory(){
            public Thread newThread(Runnable r) {
                Thread t=new Thread(r);
                t.setDaemon(true);
                t.setPriority(Thread.MAX_PRIORITY);
                return t;
            }
        });
    }
    
    /*
     * 1.调用join的需求是,希望在某个线程中执行到一部分的时候,转入另外一个指定的线程,而当前
     * 2.线程挂起,等到另外一个线程执行完了以后,再恢复到到join的点,然后执行下去
     * 3.注意,join的必须是正在运行的线程,还未启动的线程,join的时候不会启动
     * 4.join的参数,指定一定得时间,如果还未返回,那么就自动结束挂起
     * 5.join可以被interrupt, 比如:  如果一个线程,join后长时间等待后,还没有返回结果,那么在其他线程里面调用这个线程的interrupt,可以结束join等待,继续执行下去
     * 6.网上有人说interrupt害人,应该是没有搞清楚interrupt的用处,没有测试,从字面意思理解为(结束,或者关闭)
     * 真实的意思,应该是让线程结束某个等待,然后顺利执行下去
     * 7.如果是Executor执行的Thread,那么join后,将不能够interrupt
     */
    public static void testThreadJoin(){
        
        class TestJ extends Thread{
            public TestJ(){
                //必须是join正在运行的线程
                start();
            }
            public void run() {
                int i=10;
                while(i-->0){
                    
                    try {
                        TimeUnit.MILLISECONDS.sleep(500l);
                    } catch (InterruptedException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                    System.out.println("XXX");
                }
            }
        }
        
        Thread tx=new TestJ();
        
        class TestJ1 extends Thread{
            Thread t;
            
            public TestJ1(Thread tx){
                t=tx;
            }
            
            
            public void run() {
                int i=10;
                while(i>0){
                    if(i==5){
                        try {
                            t.join();
                        } catch (InterruptedException e) {
                            // TODO Auto-generated catch block
                            e.printStackTrace();
                        }
                    }
                    System.out.println(Integer.toString(i--));
                }
            }
        }
        
        ExecutorService se=Executors.newCachedThreadPool();
        Thread xx=new TestJ1(tx);
        se.execute(xx);
        //xx.start();
        
        try {
            TimeUnit.MILLISECONDS.sleep(1000l);
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        xx.interrupt();
        
        
    }
    
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics