• 《Think in Java》20 21(并发)


    chapter 20 注解

    三种标准注解和四种元注解:

    编写注解处理器

    chapter 21 并发

    基本的线程机制

    定义任务

    package cn.test;
    
    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!")+"),";
        }
        @Override
        public void run() {
            while(countDown-->0) {
                System.out.print(status());
                Thread.yield();//线程重新抢占
            }
        }
    }
    
    

    public class MainThread {
      public static void main(String[] args) {
        LiftOff launch=new LiftOff();
        launch.run();
      }
    }

     Thread类

    public class BasicThreads {
        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

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

     从任务中产生返回值

      Runnable 不会返回任何值。使用Callable接口能够返回一个值。

    package cn.test;
    
    import java.util.ArrayList;
    import java.util.concurrent.Callable;
    import java.util.concurrent.ExecutionException;
    import java.util.concurrent.ExecutorService;
    import java.util.concurrent.Executors;
    import java.util.concurrent.Future;
    
    class TaskWithResult implements Callable<String> {
        private int id;
        public TaskWithResult(int id) {
            this.id=id;
        }
        @Override
        public String call() throws Exception {
            return "result of TaskWithResult "+ id;
        }
    }
    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<10;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();
                }
            }
        }
    } 

    休眠

       Thread.sleep();

    优先级

    package cn.test;
    
    import java.util.concurrent.ExecutorService;
    import java.util.concurrent.Executors;
    
    public class SimplePriorities implements Runnable{
        private int countDown=5;
        private volatile double d;
        private int priority;
        public SimplePriorities(int priority) {
            this.priority=priority;
        }
        public String toString() {
            return Thread.currentThread()+":"+countDown;
        }
        @Override
        public void run() {
            Thread.currentThread().setPriority(priority);
            while(true) {
                for(int i=1;i<100000;i++) {
                    d+=(Math.PI+Math.E)/(double)i;
                    if(i%1000 == 0) 
                        Thread.yield();
                }
                System.out.println(this);
                if(--countDown == 0) return;
            }
        }
        public static void main(String[] args) {
            ExecutorService exec=Executors.newCachedThreadPool();
            for(int i=0;i<5;i++)
                exec.execute(new SimplePriorities(Thread.MIN_PRIORITY));
            exec.execute(new SimplePriorities(Thread.MAX_PRIORITY));
            exec.shutdown();
        }
        
        
    }

    让步

      Thread.yield();

    后台线程

      daemon线程。

    package cn.test;
    
    public class SimpleDaemons implements Runnable{
        public void run() {
            try {
            while(true) {
                    Thread.sleep(100);
                    System.out.println(Thread.currentThread()+" "+this);
            }
                } catch (Exception e) {
                    System.out.println("sleep() interrupted");
                    e.printStackTrace();
                }
        }
        public static void main(String[] args) throws InterruptedException {
            for(int i=0;i<10;i++) {
                Thread daemon=new Thread(new SimpleDaemons());
                daemon.setDaemon(true);
                daemon.start();
            }
            System.out.println("All daemons started");
            Thread.sleep(100);
        }
    
    }

    使用isDaemon()方法来确定线程是否是一个后台线程。

    package cn.test;
    
    import java.util.concurrent.TimeUnit;
    
    class Daemon implements Runnable{
        private Thread[] t=new Thread[10];
        public void run() {
            for(int i=0;i<t.length;i++) {
                t[i]=new Thread(new DaemonSpawn());
                t[i].start();
                System.out.println("DaemonSpawn "+i+" started,");
            }
            for(int i=0;i<t.length;i++)
                System.out.println("t["+i+"].siDaemon()="+
            t[i].isDaemon()+",");
            while(true) {
                Thread.yield();
            }
        }
        class DaemonSpawn implements Runnable{
            public void run() {
                while(true)
                    Thread.yield();
            }
        }
    }
    public class Daemons {
        public static void main(String[] args) throws InterruptedException {
            Thread d=new Thread(new Daemon());
            d.setDaemon(true);
            d.start();
            System.out.println("d.isDaemon()="+d.isDaemon()+",");
            TimeUnit.SECONDS.sleep(1);
            
        }
    }

    一旦main()退出,JVM就会立即关闭所有的后台进程。

    package cn.test;
    
    import java.util.concurrent.TimeUnit;
    
    class ADaemon implements Runnable{
        public void run() {
            try {
                System.out.println("Starting ADaemon");
                TimeUnit.SECONDS.sleep(1);
            }catch(Exception e) {
                System.out.println("Exiting via InterruptedException");
            }finally {
                System.out.println("This should always run?");
            }
        }
    }
    public class DaemonsDontRunFinally {
        public static void main(String[] args) throws Exception {
            Thread t= new Thread(new ADaemon());
            t.setDaemon(true);
            t.start();
    //        TimeUnit.SECONDS.sleep(1);
        }
    }

    编码的变体

    package cn.test;
    
    import java.util.concurrent.TimeUnit;
    
    class ADaemon implements Runnable{
        public void run() {
            try {
                System.out.println("Starting ADaemon");
                TimeUnit.SECONDS.sleep(1);
            }catch(Exception e) {
                System.out.println("Exiting via InterruptedException");
            }finally {
                System.out.println("This should always run?");
            }
        }
    }
    public class DaemonsDontRunFinally {
        public static void main(String[] args) throws Exception {
            Thread t= new Thread(new ADaemon());
            t.setDaemon(true);
            t.start();
    //        TimeUnit.SECONDS.sleep(1);
        }
    }

    加入一个线程【】

    package cn.test;
    class Sleeper extends Thread{
        private int duration;
        public Sleeper(String name,int sleepTime) {
            super(name);
            duration=sleepTime;
            start();
        }
        public void run() {
            try {
                sleep(duration);
            } catch(InterruptedException e) {
                System.out.println(getName()+" was interrupted ."+
                "isInterrupted():"+isInterrupted());
                return;
            }
            System.out.println(getName()+" has awakened");
        }
    }
    class Joiner extends Thread{
        private Sleeper sleeper;
        public Joiner(String name,Sleeper sleeper) {
            super(name);
            this.sleeper=sleeper;
            start();
        }
        public void run() {
            try {
                sleeper.join();
            }catch (InterruptedException e) {
                System.out.println("Interrupted");
            }
            System.out.println(getName()+" join completed");
        }
    }
    public class Joining {
        public static void main(String[] args) {
            Sleeper 
                sleepy=new Sleeper("Sleeper",1500),
                grumpy=new Sleeper("Grumpy",1500);
            Joiner 
                dopey=new Joiner("Dopey",sleepy),
                doc=new Joiner("Doc",grumpy);
            grumpy.interrupt();
        }
    }

    创建有响应的用户界面

      使用线程的动机之一就是建立有响应的用户界面。

    package cn.test;
    
    import java.io.IOException;
    
    class UnresponsiveUI{
        private volatile double d=1;
        public UnresponsiveUI() throws IOException {
            while(d>0)
                d=d+(Math.PI+Math.E)/d;
            System.in.read();
        }
    }
    public class ResponsiveUI extends Thread{
        private static volatile double d=1;
        public ResponsiveUI() {
            setDaemon(true);
            start();
        }
        @Override
        public void run() {
            while(true)
                d=d+(Math.PI+Math.E)/d;
        }
        public static void main(String[] args) throws IOException {
    //        new UnresponsiveUI();
            new ResponsiveUI();
            System.in.read();
            System.out.println(d);
        }
    }

      

    线程组

    捕获异常

      

    package cn.test;
    
    import java.util.concurrent.ExecutorService;
    import java.util.concurrent.Executors;
    
    public class ExceptionThread implements Runnable{
        public void run() {
            throw new RuntimeException();
        }
        public static void main(String[] args) {
            try {
                ExecutorService exec = Executors.newCachedThreadPool();
                exec.execute(new ExceptionThread());
            }catch(RuntimeException ue) {  //无法捕获异常
                System.out.println("Exception has been handled!");
            }
        }
    }
    package cn.test;
    
    import java.util.concurrent.ExecutorService;
    import java.util.concurrent.Executors;
    import java.util.concurrent.ThreadFactory;
    
    class ExceptionThread2 implements Runnable{
        public void run() {
            Thread t=Thread.currentThread();
            System.out.println("run() by "+t);
            System.out.println("eh = "+t.getUncaughtExceptionHandler());
            throw new RuntimeException();
        }
    }
    class MyUncaughtExceptionHandler implements Thread.UncaughtExceptionHandler{
        @Override
        public void uncaughtException(Thread t, Throwable e) {
            System.out.println("caught "+e);
        }
    }
    class HandlerThreadFactory implements ThreadFactory{
        public Thread newThread(Runnable r) {
            System.out.println(this+" creating new Thread");
            Thread t=new Thread();
            System.out.println("created "+t);
            t.setUncaughtExceptionHandler(new MyUncaughtExceptionHandler());
            System.out.println("eh="+t.getUncaughtExceptionHandler());
            return t;
        }
    }
    public class CaptureUncaughtException {
        public static void main(String[] args) {
            ExecutorService exec=Executors.newCachedThreadPool(new HandlerThreadFactory());
            exec.execute(new ExceptionThread2());
        }
    }

      

    package cn.test;
    
    import java.util.concurrent.ExecutorService;
    import java.util.concurrent.Executors;
    
    public class SettingDefaultHandler {
        public static void main(String[] args) {
            Thread.setDefaultUncaughtExceptionHandler(
                    new MyUncaughtExceptionHandler());
            ExecutorService exec = Executors.newCachedThreadPool();
            exec.execute(new ExceptionThread());
        }
    }

    共享受限资源

    不正确地访问资源

    package cn.test;
    
    import java.util.concurrent.ExecutorService;
    import java.util.concurrent.Executors;
    
    abstract class IntGenerator{
        private volatile boolean canceled=false;
        public abstract int next();
        public void cancel() {canceled=true;}
        public boolean isCanceled() {return canceled;}
    }
    public class EvenChecker implements Runnable{
        private IntGenerator generator;
        private final int id;
        public EvenChecker (IntGenerator g,int ident) {
            generator = g;
            id = ident;
        }
        public void run() {
            while(!generator.isCanceled()) {
                int val=generator.next();
                if(val%2!=0) {
                    System.out.println(val+" not even!");
                    generator.cancel();
                }
            }
        }
        public static void test(IntGenerator gp,int count) {
            System.out.println("Press Control-C to exit");
            ExecutorService exec=Executors.newCachedThreadPool();
            for(int i=0;i<count;i++) 
                exec.execute(new EvenChecker(gp,i));
            exec.shutdown();
        }
        public static void test(IntGenerator gp) {
            test(gp,10);
        }
    }
    
    package cn.test;
    
    public class EvenGenerator extends IntGenerator {
        private int currentEvenValue=0;
        public int next() {
            ++currentEvenValue;
            ++currentEvenValue;
            return currentEvenValue;
        }
        public static void main(String[] args) {
            EvenChecker.test(new EvenGenerator());
        }
    }

    在java中,递增不是原子性的操作。因此,如果不保护任务,即使单一的递增也是不安全的。

    解决共享资源竞争

      序列化访问共享资源方法。

      互斥量。

     

    (该类的其他对象调用synchronized任务的操作被锁定,只有已经进入被锁任务的那个对象完成任务后才可竞权)

    package cn.test;
    
    public class EvenGenerator extends IntGenerator {
        private int currentEvenValue=0;
        public synchronized int next() {
            ++currentEvenValue;
            Thread.yield();
            ++currentEvenValue;
            return currentEvenValue;
        }
        public static void main(String[] args) {
            EvenChecker.test(new EvenGenerator());
        }
    }

     使用显式的Lock对象

    java.util.concurrent.locks

    package cn.test;
    
    import java.util.concurrent.locks.Lock;
    import java.util.concurrent.locks.ReentrantLock;
    
    public class MutexEvenGenerator extends IntGenerator{
        private int currentEvenValue=0;
        private Lock lock=new ReentrantLock();
        public int next() {
            lock.lock();
            try {
                ++currentEvenValue;
                Thread.yield();
                ++currentEvenValue;
                return currentEvenValue;
            } finally {
                lock.unlock();
            }
        }
        public static void main(String[] args) {
            EvenChecker.test(new MutexEvenGenerator());
        }
    
    }
    package cn.test;
    
    import java.util.concurrent.TimeUnit;
    import java.util.concurrent.locks.ReentrantLock;
    
    public class AttemptLocking {
        private ReentrantLock lock=new ReentrantLock();
        public void untimed() {
            boolean captured=lock.tryLock();
            try {
                System.out.println("untimed tryLock(): "+captured);
            }finally {
                if(captured)
                    lock.unlock();
            }
        }
        public void timed() {
            boolean captured = false;
            try {
                captured = lock.tryLock(2, TimeUnit.SECONDS);
            }catch(InterruptedException e) {
                throw new RuntimeException(e);
            }
            try {
                System.out.println("timed tryLock(2,TimeUnit.SECONDS): "
            +captured);
            }finally {
                if(captured) 
                    lock.unlock();
            }
        }
        public static void main(String[] args) {
            final AttemptLocking al=new AttemptLocking();
            al.untimed();
            al.timed();
            new Thread() {
                {setDaemon(true);}
                public void run() {
                    al.lock.lock();
                    System.out.println("acquired");
                }
            }.start();
            Thread.yield();
            al.untimed();
            al.timed();
        }
    }

    原子性与易变性

    理解volatile

    java中,对域中的值做赋值和返回操作是原子性的。

    package cn.test;
    
    import java.util.concurrent.ExecutorService;
    import java.util.concurrent.Executors;
    
    public class AtomicityTest implements Runnable{
        private int i=0;
        public int getValue() {return i;}
        private synchronized void evenIncrement() {i++;i++;}
        public void run() {
            while(true)
                evenIncrement();
        }
        public static void main(String[] args) {
            ExecutorService exec = Executors.newCachedThreadPool();
            AtomicityTest at = new AtomicityTest();
            exec.execute(at);
            while(true) {
                int val=at.getValue();
                if(val % 2 != 0) {
                    System.out.println(val);
                    System.exit(0);
                }
            }
        }
    }

     原子类

    package cn.test;
    
    import java.util.Timer;
    import java.util.TimerTask;
    import java.util.concurrent.ExecutorService;
    import java.util.concurrent.Executors;
    import java.util.concurrent.atomic.AtomicInteger;
    
    public class AtomicIntegerTest implements Runnable{
        private AtomicInteger i=new AtomicInteger(0);
        public int getValue() {return i.get();}
        private void evenIncrement() {i.addAndGet(2);}
        public void run() {
            while(true)
                evenIncrement();
        }
        public static void main(String[] args) {
            new Timer().schedule(new TimerTask() {
                public void run() {
                    System.err.println("Aborting");
                    System.exit(0);
                }
            }, 5000);
            ExecutorService exec=Executors.newCachedThreadPool();
            AtomicIntegerTest ait=new AtomicIntegerTest();
            exec.execute(ait);
            while(true) {
                int val=ait.getValue();
                if(val % 2 != 0) {
                    System.out.println(val);
                    System.exit(0);
                }
            }
        }
    
    }

    临界区(同步控制块)【】

    在其他对象上同步

    package cn.test;
    class DualSynch{
        private Object syncObject = new Object();
        public synchronized void f() {
            for(int i=0;i<5;i++) {
                System.out.println("f()");
                Thread.yield();
            }
        }
        public void g() {
            synchronized(syncObject) {
                for(int i=0;i<5;i++) {
                    System.out.println("g()");
                    Thread.yield();
                }
            }
        }
    }
    public class SyncObject {
        public static void main(String[] args) {
            final DualSynch ds=new DualSynch();
            new Thread() {
                public void run() {
                    ds.f();
                }
            }.start();
            ds.g();
        }
    }

    线程本地存储【】

    package cn.test;
    
    import java.util.Random;
    import java.util.concurrent.ExecutorService;
    import java.util.concurrent.Executors;
    import java.util.concurrent.TimeUnit;
    
    class Accessor implements Runnable{
        private final int id;
        public Accessor (int idn) {id=idn;}
        public void run() {
            while(!Thread.currentThread().isInterrupted()) {
                ThreadLocalVariableHolder.increment();
                System.out.println(this);
                Thread.yield();
            }
        }
        public String toString() {
            return "#"+id+": "+ThreadLocalVariableHolder.get();
        }
    }
    public class ThreadLocalVariableHolder {
        private static ThreadLocal<Integer> value=
                new ThreadLocal<Integer>() {
            private Random rand=new Random(47);
            protected synchronized Integer initialValue() {
                return rand.nextInt(10000);
            }
        };
        public static void increment() {
            value.set(value.get()+1);
        }
        public static int get() {return value.get();}
        public static void main(String[] args) throws InterruptedException {
            ExecutorService exec = Executors.newCachedThreadPool();
            for(int i=0;i<5;i++)
                exec.execute(new Accessor(i));
            TimeUnit.SECONDS.sleep(3);
            exec.shutdown();
        }
    }
    package cn.test;
    
    import java.util.Random;
    import java.util.concurrent.ExecutorService;
    import java.util.concurrent.Executors;
    import java.util.concurrent.TimeUnit;
    
    class Accessor implements Runnable{
        private final int id;
        public Accessor (int idn) {id=idn;}
        public void run() {
            while(!Thread.currentThread().isInterrupted()) {
                ThreadLocalVariableHolder.increment();
                System.out.println(this);
                Thread.yield();
            }
        }
        public String toString() {
            return "#"+id+": "+ThreadLocalVariableHolder.get();
        }
    }
    public class ThreadLocalVariableHolder {
        private static ThreadLocal<Integer> value=
                new ThreadLocal<Integer>() {
            private Random rand=new Random(47);
            protected synchronized Integer initialValue() {
                return rand.nextInt(10000);
            }
        };
        public static void increment() {
            value.set(value.get()+1);
        }
        public static int get() {return value.get();}
        public static void main(String[] args) throws InterruptedException {
            ExecutorService exec = Executors.newCachedThreadPool();
            for(int i=0;i<5;i++)
                exec.execute(new Accessor(i));
            TimeUnit.SECONDS.sleep(3);
            exec.shutdown();
        }
    }

    终结任务

    装饰性花园

    package cn.test;
    
    import java.util.ArrayList;
    import java.util.List;
    import java.util.Random;
    import java.util.concurrent.ExecutorService;
    import java.util.concurrent.Executors;
    import java.util.concurrent.TimeUnit;
    
    class Count{
        private int count=0;
        private Random rand=new Random(47);
        public synchronized int increment() {
            int temp=count;
            if(rand.nextBoolean())
                Thread.yield();
            return (count= ++temp);
        }
        public synchronized int value() {return count;}
    }
    class Entrance implements Runnable{
        private static Count count=new Count();
        private static List<Entrance> entrances=
                new ArrayList<Entrance>();
        private int number=0;
        private final int id;
        private static volatile boolean canceled=false;
        public static void cancel() {canceled =true;}
        public Entrance(int id) {
            this.id=id;
            entrances.add(this);
        }
        public void run() {
            while(!canceled) {
                synchronized(this) {
                    ++number;
                }
                System.out.println(this+"Total: "+count.increment());
                try {
                    TimeUnit.MICROSECONDS.sleep(100);
                }catch(InterruptedException e) {
                    System.out.println("sleep interrupted");
                }
            }
            System.out.println("Stopping "+this);
        }
        public synchronized int getValue() {return number;}
        public String toString() {
            return "Entrance "+id+": "+getValue();
        }
        public static int getTotalCount() {
            return count.value();
        }
        public static int sumEntrances() {
            int sum=0;
            for(Entrance entrance:entrances)
                sum+=entrance.getValue();
            return sum;
        }
    }
    public class OrnamentalGarden {
        public static void main(String[] args) throws InterruptedException {
            ExecutorService exec = Executors.newCachedThreadPool();
            for(int i=0;i<5;i++)
                exec.execute(new Entrance(i));
            TimeUnit.SECONDS.sleep(3);
            Entrance.cancel();
            exec.shutdown();
            if(!exec.awaitTermination(250, TimeUnit.MICROSECONDS))
                System.out.println("Some tasks were not terminated!");
            System.out.println("Total: "+Entrance.getTotalCount());
            System.out.println("Sum of Entrances: "+Entrance.sumEntrances());
        }
    }

     在阻塞时终结

    线程状态:

    1. 新建
    2. 就绪
    3. 阻塞
    4. 死亡

    进入阻塞状态

      调用sleep(milliseconds)会进入休眠状态,设定的时间结束时继续运行。

      调用wait()使线程挂起,直到线程被notify()或notifyAll(),线程会进入就绪状态。

      当前任务的等待输入/输出。

      当然任务被阻塞在锁外。

    中断

       cancel()是一种中断由Executor启动的单个线程的方式。

    package cn.test;
    
    import java.io.IOException;
    import java.io.InputStream;
    import java.util.concurrent.ExecutorService;
    import java.util.concurrent.Executors;
    import java.util.concurrent.Future;
    import java.util.concurrent.TimeUnit;
    
    class SleepBlocked implements Runnable{
        public void run() {
            try {
                TimeUnit.SECONDS.sleep(100);
            } catch(InterruptedException e) {
                System.out.println("InterruptedException");
            }
            System.out.println("Exiting SleepBlocked.run() ");
        }
    }
    class IOBlocked implements Runnable{
        private InputStream in;
        public IOBlocked(InputStream in) {this.in = in;    }
        public void run() {
            try {
                System.out.println("Waiting for read():");
                in.read();
            } catch (IOException e) {
                if(Thread.currentThread().isInterrupted()) 
                    System.out.println("Interrupted from blocked I/O");
                else
                    throw new RuntimeException();
            }
            System.out.println("Exiting IOBlocked.run() ");
        }
        
    }
    class SynchronizedBlocked implements Runnable{
        public synchronized void f() {
            while(true)
                Thread.yield();
        }
        public SynchronizedBlocked() {
            new Thread() {
                public void run() {
                    f();
                }
            }.start();
        }
        public void run() {
            System.out.println("Trying to call f()");
            f();
            System.out.println("Exiting SynchronizedBlocked.run()");
        }
    }
    public class Interrupting {
        private static ExecutorService exec=
                Executors.newCachedThreadPool();
        static void test(Runnable r) throws InterruptedException {
            Future<?> f= exec.submit(r);
            TimeUnit.MICROSECONDS.sleep(100);
            System.out.println("Interrupting "+r.getClass().getName());
            f.cancel(true);
            System.out.println("Interrupt sent to "+r.getClass().getName());
        }
        public static void main(String[] args) throws Exception {
            test(new SleepBlocked());
            test(new IOBlocked(System.in));
            test(new SynchronizedBlocked());
            TimeUnit.SECONDS.sleep(3);
            System.out.println("Aborting with System.exit(0)");
            System.exit(0);
        }
    }

     被互斥所阻塞【】

    package cn.test;
    
    public class MultiLock {
        public synchronized void f1(int count) {
            if(count-- >0) {
                System.out.println("f1() calling f2() with count "+count);
                f2(count);
            }
        }
        public synchronized void f2(int count) {
            if(count-- >0) {
                System.out.println("f2() calling f1() with count "+count);
                f1(count);
            }
        }
        public static void main(String[] args) {
            final MultiLock multiLock=new MultiLock();
            new Thread() {
                public void run() {
                    multiLock.f1(10);
                }
            }.start();
        }
    }
    package cn.test;
    
    import java.util.concurrent.TimeUnit;
    import java.util.concurrent.locks.Lock;
    import java.util.concurrent.locks.ReentrantLock;
    
    class BlockedMutex{
        private Lock lock=new ReentrantLock();
        public BlockedMutex() {
            lock.lock();
        }
        public void f() {
            try {
                lock.lockInterruptibly();
                System.out.println("lock acquired in f()");
            } catch (InterruptedException e) {
                System.out.println("Interrupted from lock acquisition in f()");
            }
        }
    }
    class Blocked2 implements Runnable {
        BlockedMutex blocked=new BlockedMutex();
        public void run() {
            System.out.println("Waiting for f() in BlockedMutex");
            blocked.f();
            System.out.println("Broken out of blocked call");
        }
    }
    public class Interrupting2 {
        public static void main(String[] args) throws Exception {
            Thread t= new Thread(new Blocked2());
            t.start();
            TimeUnit.SECONDS.sleep(1);
            System.out.println("Issuing t.interrupt()");
            t.interrupt();
        }
    }

     检查中断

     线程之间的协作

    wait()与notifyAll() 

    package cn.test;
    
    import java.util.concurrent.ExecutorService;
    import java.util.concurrent.Executors;
    import java.util.concurrent.TimeUnit;
    
    class Car{
        private boolean waxOn=false;
        public synchronized void waxed() {
            waxOn=true;
            notifyAll();
        }
        public synchronized void buffed() {
            waxOn=false;
            notifyAll();
        }
        public synchronized void waitForWaxing() throws InterruptedException {
            while(waxOn== false)
                wait();
        }
        public synchronized void waitForBuffing() throws InterruptedException {
            while(waxOn== true)
                wait();
        }
    }
    class WaxOn implements Runnable{
        private Car car;
        public WaxOn(Car c) {car= c;} 
        public void run() {
            try {
                while(!Thread.interrupted()) {
                    System.out.println("Wax On!");
                    TimeUnit.MILLISECONDS.sleep(200);
                    car.waxed();
                    car.waitForBuffing();
                }
            }catch(InterruptedException e) {
                System.out.println("Exiting via interrupt");
            }
            System.out.println("Ending Wax On task");
        }
    }
    class WaxOff implements Runnable{
        private Car car;
        public WaxOff(Car c) {car=c;}
        public void run() {
            try {
                while(!Thread.interrupted()) {
                    car.waitForWaxing();
                    System.out.println("Wax Off!");
                    TimeUnit.MILLISECONDS.sleep(200);
                    car.buffed();
                }
            }catch(InterruptedException e) {
                System.out.println("Exiting via interrupt");
            }
            System.out.println("Ending Wax Off task");
        }
    }
    public class WaxOMatic {
        public static void main(String[] args) throws Exception {
            Car car=new Car();
            ExecutorService exec = Executors.newCachedThreadPool();
            exec.execute(new WaxOff(car));
            exec.execute(new WaxOn(car));
            TimeUnit.SECONDS.sleep(5);
            exec.shutdownNow();
        }
    }

      

  • 相关阅读:
    webservice的两种客户端调用方式(总结)
    Maven笔记
    在myeclipse中建立webservice,发布webservice并且调用webservice接口
    1分钟内使用Adobe Dreamweaver CS5建立导航菜单
    Asp.Net Cookie的清除
    常用的sql标准建表语句
    Java5的 线程并发库
    使用NPOI操作Excel
    使用.net 内置的SmtpClient来实现邮件的发送
    qlikview 地图插件制作教程
  • 原文地址:https://www.cnblogs.com/mryangbo/p/10315761.html
Copyright © 2020-2023  润新知