当前位置:编程学习 > JAVA >>

线程笔记之并发同步

在应用编程中,我们会遇到下面这样的调用模型。。。
 

\
 当一个业务方法(begin)中顺序调用多个子业务方法(opertion1-N),且有些子业务方法比较耗时,那么自然而然完成这次调用所需要的时间就比较长了。对于这样的问题,通常情况下会从两个方面对其进行重构和调优:
 
单个方法调优,即针对operation1-N中比较耗时的方法进行重构已达到期望的效果
业务重组和方法重构,即对整个大的业务方法进行重组,找出合乎当前需求(功能和性能)的实现方式
1比较好理解,最常见的就是sql语句,IO和string buffer方面的调优;2则需要看具体的应用场景了。由于本文主要是侧重线程的并发与同步,所以我将例举一个比较特殊的场景(webservices 远程调用)。如下:
 

\
 
 
对照上述序列图,若每一个operation方法都将进行一次远程webservice调用,那么一次调用的代价就要包含网络通信方面的开销。如果网络延时很高,多次远程调用的代价就相当大了。那么该如果结合上面的第2点进行重构和调优呢?
 
减少网络调用次数。 例如 operation1->API1,operation2->API2, 那么是否可以提供一个包含API1和API2的新API12供其调用呢?这样一次调用就可以达到目的。
多线程调用。如,让operation1与operation2并发,这样调用所需要的时间则为max(cost(operation1), cost(operation2))。这样做会大大提高系统的复杂性,谨慎而为之。
 
接下来进入主题,谈谈并发的具体实现方式。
 
基本测试类ConcurrentSimpleTest
 
Java代码 
public class ConcurrentSimpleTest { 
 
    public void method1() { 
        System.out.println("before exec method1"); 
        try { 
            Thread.sleep(400); 
        } catch (InterruptedException e) { 
            // TODO Auto-generated catch block 
            System.out.println("method1 has been interrupted."); 
            e.printStackTrace(); 
             
        } 
        System.out.println("after exec method1"); 
    } 
 
    public void method2() { 
        System.out.println("before exec method2"); 
        try { 
            Thread.sleep(800); 
        } catch (InterruptedException e) { 
            // TODO Auto-generated catch block 
            System.out.println("method2 has been interrupted."); 
            e.printStackTrace(); 
             
        } 
        System.out.println("after exec method2"); 
    } 

 
 
方式1:使用线程的join方法
Java代码 
public static void main(String[] args) throws InterruptedException { 
        final ConcurrentSimpleTest cst = new ConcurrentSimpleTest(); 
         
        long s1 = System.currentTimeMillis(); 
        cst.method1();  
        cst.method2(); 
        long s2 = System.currentTimeMillis();    
         
        Thread t1 = new Thread(new Runnable() { 
            @Override 
            public void run() { 
                cst.method1();  
            } 
        }); 
 
        Thread t2 = new Thread(new Runnable() { 
            @Override 
            public void run() { 
                cst.method2(); 
            } 
        }); 
         
        t1.start(); 
        t2.start(); 
         
        t1.join(); //t2.join(500); 实际400ms后,方法就返回了 
        t2.join(); //t1.join(x); if x< max((800 - 400), (800-500)), 那该方易做图在t2执行完前返回 
         
        //线程1/2都已返回,需要验证结果 
         
        long s3 = System.currentTimeMillis(); 
         
        System.out.println("time cost for normal execution:" + (s2-s1)); 
        System.out.println("time cost for concurrent execution:" + (s3-s2)); 
    } 
 
 
方式2:使用信号量对象
 
自定义信号量
Java代码 
public class SimpleMonitor { 
        public volatile int single = 0; 
 
        public void require(int single) { 
            this.single = single; 
        } 
 
        public synchronized void release(int single) { 
            this.single -= single; 
            this.notify(); 
        } 
    } 
 
 
Java代码 
public static void main(String[] args) throws InterruptedException { 
        final ConcurrentSimpleTest cst = new Concur

补充:软件开发 , Java ,
CopyRight © 2022 站长资源库 编程知识问答 zzzyk.com All Rights Reserved
部分文章来自网络,