zoukankan      html  css  js  c++  java
  • 并发1

    实现并发最直接的方式是在操作系统级别使用进程,进程是运行在它自己的地址空间内的自包容的程序。多任务操作系统可以通过周期性地将CPU从一个进程切换到另一个进程,来实现同时运行多个进程。

    并发提供了一个重要的组织结构上的好处,可以使程序设计极大地简化。

    下面的LiftOff任务将显示发射之前的倒计时:

    public class LiftOff implements Runnable{
        protected int countDown=10;
        private static int taskCount=0;
        private final int id=taskCount++;
        public LiftOff(){}
        public LiftOff(int countDown){
            this.countDown=countDown;
        }
        public String status(){
            return "#"+id+"("+(countDown>0?countDown:"LiftOff")+").";
        }
        public void run(){
            while(countDown-->0){
                System.out.println(status());
                Thread.yield();
            }
        }
        public static void main(String[] args) {
            LiftOff lo=new LiftOff();
            lo.run();
        }
    }
    不同任务的执行在线程被换进换出时混在了一起,这种交换是由线程调度器自动控制的。

    如:

    public class MoreBasicThreads {
        public static void main(String[] args) {
            for(int i=0;i<5;i++)
                new Thread(new LiftOff()).start();;
                System.out.println("Waiting for LiftOff");
        }
    }

    Executor用来管理Thread对象,从而简化了并发编程。Executor在客户端和任务执行之间提供了一个间接层,与客户端直接执行任务不同,这个中介对象将执行任务。Executor可以用来管理异步任务的执行,而无须显式地管理线程的生命周期。

    import java.util.concurrent.ExecutorService;
    import java.util.concurrent.Executors;

    public class CachedThreadPool {
        public static void main(String[] args) {
            ExecutorService exec=Executors.newCachedThreadPool();
            for(int i=0;i<5;i++)
                exec.execute(new LiftOff());
            exec.shutdown();
        }
    }

    Runnable是执行工作的独立任务,但是它不返回任何值。如果希望任务在完成时能够返回一个值,那么可以实现Callable接口而不是Runnable接口.

    import java.util.concurrent.Callable;

    public class TaskWithResult implements Callable<String>{
        private int id;
        public TaskWithResult(int id){
            this.id=id;
        }
        public String call(){
            return "result of TaskWithResult"+id;
        }
    }

    import java.util.ArrayList;
    import java.util.concurrent.ExecutionException;
    import java.util.concurrent.ExecutorService;
    import java.util.concurrent.Executors;
    import java.util.concurrent.Future;

    public class CallableDemo {
        public static void main(String[] args) {
            ExecutorService exec=Executors.newCachedThreadPool();
            ArrayList<Future<String>> results=new ArrayList<Future<String>>();
            for(int i=0;i<5;i++)
                results.add(exec.submit(new TaskWithResult(i)));
            for(Future<String>fs:results)
                try{
                    System.out.println(fs.get());
                }catch(InterruptedException e){
                    System.out.println(e);
                    return;
                }catch(ExecutionException e){
                    System.out.println(e);
                }finally{
                    exec.shutdown();
                }
        }
    }

    影响任务行为的一种简单方法是调用sleep(),这将使任务中止给定的时间。

    import java.util.concurrent.ExecutorService;
    import java.util.concurrent.Executors;
    import java.util.concurrent.TimeUnit;

    public class SleepingTask extends LiftOff{
        public void run(){
            try{
                while(countDown-- > 0){
                    System.out.println(status());
                    TimeUnit.MILLISECONDS.sleep(100);
                }
            }catch(InterruptedException e){
                System.err.println("Interrupted");
            }
        }
        public static void main(String[] args) {
            ExecutorService exec=Executors.newCachedThreadPool();
            for(int i=0;i<5;i++)
                exec.execute(new SleepingTask());
            exec.shutdown();
        }
    }
    附加:对sleep()的调用可以抛出InterruptedException异常,上述例子中,其早run()中被捕获,因为异常不能跨线程传播回main(),所以必须在本地处理在任务内部产生的异常。

    上述任务是完美分布的,0到4,再回头0到4。这是很有意义的,在每个打印语句之后,每个任务都将要睡眠,这使得线程调度器可以切换到另一个线程,进而驱动另一个任务。

    注意!:顺序行为依赖于底层的线程机制,这种机制在不同的操作系统之间是有差异的,因此,不能依赖于sleep()!  而必须控制任务执行的顺序。

    ---恢复内容结束---

  • 相关阅读:
    tomcat7简单优化
    java向上转型和向下转型
    字符串循环移位
    测试覆盖率问题
    悬挂指针
    标准库string的用法探讨
    野指针问题
    Clock函数用法
    配置信息写入到.ini文件中的方法
    数组指针和数组引用做参数的区别
  • 原文地址:https://www.cnblogs.com/daochong/p/4836890.html
Copyright © 2011-2022 走看看