Java多线程高并发,代码示例(四)

前言

项目主体源码可以从ConcurrenceBasics获得,喜欢的朋友可以点个star~。

卖火车票问题(一)
/**
 * 有N张火车票,每张票都有一个编号,同时有10个窗口对外售票。
 * 分析下面的程序可能会产生哪些问题?
 * 重复销售?超量销售?
 * 问题:有可能卖重复,remove也不是原子性的。
 */
public class TicketSeller1 {
    static List<String> tickets = new ArrayList<>();
    static {
        for (int i = 0; i < 10000; i++)
            tickets.add("票编号:" + i);
    }

    public static void main(String[] args) {
        for (int i = 0; i < 10; i++){
            new Thread(()->{
                while (tickets.size() > 0){
                    System.out.println("销售了--" + tickets.remove(0));
                }
            }).start();
        }
    }
}
卖火车票问题(二)
/**
 * 有N张火车票,每张票都有一个编号,同时有10个窗口对外售票。
 * 分析下面的程序可能会产生哪些问题?
 * 问题:判断与操作分离了。
 */
public class TicketSeller2 {
    static Vector<String> tickets = new Vector<>();
    static {
        for (int i = 0; i < 1000; i++)
            tickets.add("票编号:" + i);
    }

    public static void main(String[] args) {
        for(int i = 0; i < 10; i++){
            new Thread(()->{
                while (tickets.size() > 0){
                    //这部分可能会会被打断,实际开发中也有可能出现,所以需谨慎
                    try {
                        TimeUnit.SECONDS.sleep(10);
                    }catch (InterruptedException e){
                        e.printStackTrace();
                    }
                    System.out.println("销售了--" + tickets.remove(0));
                }
            }).start();
        }
    }
}
卖火车票问题(三)
/**
 * 有N张火车票,每张票都有一个编号,同时有10个窗口对外售票。
 * 分析下面的程序可能会产生哪些问题?
 * 运行结果:运行结果没有问题,相当于把判断与操作加到一个锁里面,属于一个原子。但是效率不高。
 */
public class TicketSeller3 {
    static List<String> tickets = new LinkedList<>();
    static {
        for (int i = 0; i < 1000; i++)
            tickets.add("票编号:" + i);
    }

    public static void main(String[] args) {
        for (int i = 0; i < 10; i++){
            new Thread(()->{
                while (true){
                    synchronized (tickets){
                        if(tickets.size() <= 0) break;
                        try {
                            TimeUnit.SECONDS.sleep(10);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                        System.out.println("销售了--" + tickets.remove(0));
                    }
                }
            }).start();
        }
    }
}
买火车票问题(四)
/**
 * 有N张火车票,每张票都有一个编号,同时有10个窗口对外售票。
 * 运行结果:效率高,这里下面判断与操作并不是原子性,但是为什么没有问题,因为这里判断以后没有对值做修改操作。
 */
public class TicketSeller4 {
    static Queue<String> tickets = new ConcurrentLinkedQueue<>();
    static {
        for (int i = 0; i < 1000; i++)
            tickets.add("票编号:" + i);
    }

    public static void main(String[] args) {
        for (int i = 0; i < 10; i++){
            new Thread(()->{
                while (true){
                    String s = tickets.poll();
                    if(s == null) break;
                    else System.out.println("销售了--" + s);
                }
            }).start();
        }
    }
}
有界队列
/**
 * 有界队列
 */
public class ArrayBlockingQueueTs {
    static BlockingQueue<String> strs = new ArrayBlockingQueue<>(10);
    //static Random r = new Random();

    public static void main(String[] args) throws InterruptedException {
        for(int i = 0; i < 10; i++){
            strs.put("a" + i);
        }
        //会一直等待,等待strs空一位然后添加进去,满了会阻塞
        //strs.put("aaa");
        //会报异常
        //strs.add("aaa");
        //不会报异常,因为它会有一个boolean返回值
        //strs.offer("aaa");
        //这里意思是一秒钟后,没有添加成功就不往里面继续加了
        //strs.offer("aaa", 1, TimeUnit.SECONDS);

        System.out.println(strs);
    }
}
无界队列
/**
 * 无界队列
 */
public class LinkedBlockingQueueTs {
    static BlockingQueue<String> strs = new LinkedBlockingQueue<>();
    static Random r = new Random();

    public static void main(String[] args) {
        new Thread(()->{
            for(int i = 0; i < 100; i++){
                try {
                    strs.put("a" + i); //如果满了,就会等待
                    TimeUnit.MILLISECONDS.sleep(r.nextInt(1000));
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }, "p1").start();

        for (int i = 0; i < 5; i++){
            new Thread(()->{
                for (;;){
                    try {
                        System.out.println(Thread.currentThread().getName() + " tack - " + strs.take());//如果空了,则生成
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }, "c" + i).start();
        }
    }
}
并发容器,效率对比
/**
 * 并发容器,效率对比
 */
public class ConcurrentMap {

    public static void main(String[] args) {
        //ConcurrentHashMap这里就是把锁分成16段,每段执行的时候加上那一段锁,所以效率相对比较高
        Map<String, String> map = new ConcurrentHashMap<>();
        //Map map = new ConcurrentSkipListMap<>();

        //Map map = new Hashtable<>();
        //Map map = new HashMap<>();
        Random r = new Random();
        Thread[] ths = new Thread[100];
        //门闩计数器
        CountDownLatch latch = new CountDownLatch(ths.length);
        long start = System.currentTimeMillis();
        for(int i = 0; i < ths.length; i++){
            ths[i] = new Thread(()->{
                for (int j = 0; j < 10000; j++)
                    map.put("a" + r.nextInt(100000), "a" + r.nextInt(100000));
                latch.countDown();
            });
        }

        Arrays.asList(ths).forEach(t->t.start());
        try {
            latch.await();
        }catch (InterruptedException e){
            e.printStackTrace();
        }
        long end = System.currentTimeMillis();
        System.out.println(end - start);
    }
}
队列
/**
 * 队列
 */
public class ConcurrentQueue {
    public static void main(String[] args) {
        Queue<String> strs = new ConcurrentLinkedQueue<>();
        for (int i = 0; i < 10; i++){
            strs.offer("a" + i);
        }
        //size  = 10
        System.out.println(strs);
        System.out.println(strs.size());

        //size = 9,poll是拿出来删了
        System.out.println(strs.poll());
        System.out.println(strs.size());

        //size = 9,peek是拿出来不删
        System.out.println(strs.peek());
        System.out.println(strs.size());

        //还有双向队列
    }
}
写时复制容器copy on write
/**
 * 写时复制容器copy on write
 * 多线程环境下,写时效率低,读时效率高
 * 适合写少读多的环境
 */
public class CopyOnWriteList {
    public static void main(String[] args) {
        List<String> lists =
                //new ArrayList<>();//这个会出并发问题!
                //new Vector<>();
                new CopyOnWriteArrayList<>();
        Random r = new Random();
        Thread[] ths = new Thread[100];
        for(int i = 0; i < ths.length; i++){
            Runnable task = new Runnable() {
                @Override
                public void run() {
                    for (int i = 0; i < 1000; i++)  lists.add("a" + r.nextInt(10000));
                }
            };
            ths[i] = new Thread(task);
        }
        runAndComputeTime(ths);
        System.out.println(lists.size());
    }

    static void runAndComputeTime(Thread[] ths){
        long s1 = System.currentTimeMillis();
        Arrays.asList(ths).forEach(t->t.start());
        Arrays.asList(ths).forEach(t->{
            try {
                t.join();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        });
        long s2 = System.currentTimeMillis();
        System.out.println(s2 - s1);
    }
}
DelayQueue等待时间长的先往外拿
/**
 * DelayQueue等待时间长的先往外拿,可以用来做定时执行任务。
 */
public class DelayQueueTs {
    static BlockingQueue<MyTask> tasks = new DelayQueue();

    static Random r = new Random();

    private static class MyTask implements Delayed {

        long runningTime;
        MyTask(long rt){
            this.runningTime = rt;
        }

        @Override
        public long getDelay(TimeUnit unit) {
            return unit.convert(runningTime - System.currentTimeMillis(), TimeUnit.MILLISECONDS);
        }

        @Override
        public int compareTo(Delayed o) {
            if(this.getDelay(TimeUnit.MILLISECONDS) < o.getDelay(TimeUnit.MILLISECONDS)){
                return -1;
            }else if(this.getDelay(TimeUnit.MILLISECONDS) > o.getDelay(TimeUnit.MILLISECONDS)){
                return 1;
            }else{
                return 0;
            }
        }

        @Override
        public String toString() {
            return "" + runningTime;
        }
    }

    public static void main(String[] args) throws InterruptedException {
        long now = System.currentTimeMillis();
        MyTask t1 = new MyTask(now + 1000);
        MyTask t2 = new MyTask(now + 2000);
        MyTask t3 = new MyTask(now + 1500);
        MyTask t4 = new MyTask(now + 2500);
        MyTask t5 = new MyTask(now + 500);
        tasks.put(t1);
        tasks.put(t2);
        tasks.put(t3);
        tasks.put(t4);
        tasks.put(t5);
        System.out.println(tasks);
        for (int i = 0; i < 5; i++){
            System.out.println(tasks.take());
        }
    }
}
加锁list和没加锁list
/**
 * 加锁list和没加锁list
 */
public class SynChronizedList {
    public static void main(String[] args) {
        List<String> strs = new ArrayList<>();
        List<String> strSync = Collections.synchronizedList(strs); //加锁list
    }
}
TransferQueue意思是消费者先启动,然后生产者启动看消费者有没有启动有的话直接跳过队列跟消费者交互
public class TransferQueueTs {
    public static void main(String[] args) throws InterruptedException {
        LinkedTransferQueue<String> strs = new LinkedTransferQueue<>();
        new Thread(()->{
            try {
                System.out.println(strs.take());
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }).start();
        //如果找不到消费者的情况下会阻塞
        strs.transfer("aaa");
        /*new Thread(()->{
            try {
                System.out.println(strs.take());
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }).start();*/
    }
}
SynchronizedQueue
public class SynchronizedQueueTs {
    public static void main(String[] args) throws InterruptedException {
        BlockingQueue<String> strs = new SynchronousQueue<>();
        new Thread(()->{
            try {
                System.out.println(strs.take());
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }).start();
        strs.put("aaa"); //阻塞等待消费者消费
        //strs.add("aaa");
        System.out.println(strs.size());
    }
}
ThreadPool
/**
 * 线程池
 */
public class ThreadPool {
    public static void main(String[] args) throws InterruptedException {
        ExecutorService service = Executors.newFixedThreadPool(5);//execute submit
        for(int i = 0; i < 6; i++){
            service.execute(()->{
                try {
                    TimeUnit.MILLISECONDS.sleep(500);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println(Thread.currentThread().getName());
            });
        }
        System.out.println(service);

        service.shutdown();
        System.out.println(service.isTerminated());
        System.out.println(service.isShutdown());
        System.out.println(service);

        TimeUnit.SECONDS.sleep(5);
        System.out.println(service.isTerminated());
        System.out.println(service.isShutdown());
        System.out.println(service);
    }
}
缓存线程池CachedPool
/**
 * 缓存线程池,它的意思是要多少线程它创建多少,当然也有范围限制,
 * int的最大值,当线程60秒没有执行,将关闭该线程。
 */
public class CachedPoolTs {
    public static void main(String[] args) throws InterruptedException {
        ExecutorService service = Executors.newCachedThreadPool();
        System.out.println(service);

        for(int i = 0; i < 2; i++){
            service.execute(()->{
                try {
                    TimeUnit.MILLISECONDS.sleep(500);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println(Thread.currentThread().getName());
            });
        }

        System.out.println(service);
        TimeUnit.SECONDS.sleep(66);
        System.out.println(service);
    }
}
ForkJoinPool
public class ForkJoinPoolTs {

    static int[] nums = new int[1000000];
    static final int MAX_NUM = 50000;
    static Random r = new Random();

    static {
        for(int i = 0; i < nums.length; i++){
            nums[i] = r.nextInt(100);
        }
        System.out.println(Arrays.stream(nums).sum()); //stream api
    }

    /*static class AddTask extends RecursiveAction{
        int start, end;

        AddTask(int start, int end){
            this.start = start;
            this.end = end;
        }

        @Override
        protected void compute() {
            if(end - start <= MAX_NUM){
                long sum = 0L;
                for(int i = start; i < end; i++) sum += nums[i];
                System.out.println("from:" + start + "to:" + end + " = " + sum);
            }else{
                int middle = start + (end - start)/2;
                AddTask subTask1 = new AddTask(start, middle);
                AddTask subTask2 = new AddTask(middle, start);
                subTask1.fork();
                subTask2.fork();
            }
        }
    }*/

    static class AddTask extends RecursiveTask<Long>{
        int start, end;
        AddTask(int start, int end){
            this.start = start;
            this.end = end;
        }

        @Override
        protected Long compute() {
            if(end - start <= MAX_NUM){
                long sum = 0L;
                for(int i = start; i < end; i++) sum += nums[i];
                return sum;
            }
            int middle = start + (end - start)/2;
            AddTask subTask1 = new AddTask(start, middle);
            AddTask subTask2 = new AddTask(middle, end);
            subTask1.fork();
            subTask2.fork();
            return subTask1.join() + subTask2.join();
        }
    }

    public static void main(String[] args) throws IOException {
        ForkJoinPool forkJoinPool = new ForkJoinPool();
        AddTask task = new AddTask(0, nums.length);
        forkJoinPool.execute(task);
        long result = task.join();
        System.out.println(result);
        //System.in.read();
    }

}
Future
public class FutureTs {
    public static void main(String[] args) throws ExecutionException, InterruptedException {
        //new Callable() {Integer call();}
        FutureTask<Integer> task = new FutureTask<>(()->{
            TimeUnit.MILLISECONDS.sleep(500);
            return 1000;
        });
        new Thread(task).start();
        System.out.println(task.get());//阻塞

        ExecutorService service = Executors.newFixedThreadPool(5);
        Future<Integer> f = service.submit(()->{
            TimeUnit.MILLISECONDS.sleep(500);
            return 1;
        });
        //阻塞完以后f.get后,在f.isDone(),会返回true,否则false
        //System.out.println(f.get());
        System.out.println(f.isDone());
    }
}
线程池,并行计算,ParallelComputing
/**
 * 线程池,并行计算
 */
public class ParallelComputing {
    public static void main(String[] args) throws ExecutionException, InterruptedException {
        //这里进行普通的计算
        long start = System.currentTimeMillis();
        List<Integer> results = getPrime(1, 200000);
        long end = System.currentTimeMillis();
        System.out.println(end - start);

        //这里类似于分四个线程,然后一起对结果进行计算
        final int cpuCoreNum = 4;
        ExecutorService service = Executors.newFixedThreadPool(cpuCoreNum);

        MyTask t1 = new MyTask(1, 80000);
        MyTask t2 = new MyTask(80001, 130000);
        MyTask t3 = new MyTask(130001, 170000);
        MyTask t4 = new MyTask(170001, 200000);

        Future<List<Integer>> f1 = service.submit(t1);
        Future<List<Integer>> f2 = service.submit(t2);
        Future<List<Integer>> f3 = service.submit(t3);
        Future<List<Integer>> f4 = service.submit(t4);

        start = System.currentTimeMillis();
        f1.get();
        f2.get();
        f3.get();
        f4.get();
        end = System.currentTimeMillis();
        System.out.println(end - start);
    }

    static class MyTask implements Callable<List<Integer>>{
        int startPos, endPos;

        MyTask(int startPos, int endPos) {
            this.startPos = startPos;
            this.endPos = endPos;
        }

        @Override
        public List<Integer> call() throws Exception {
            List<Integer> r = getPrime(startPos, endPos);
            return r;
        }
    }

    static boolean isPrime(int num){
        for(int i = 2; i <= num/2; i++){
            if(num % i == 0)
                return false;
        }
        return true;
    }

    static List<Integer> getPrime(int start, int end){
        List<Integer> results = new ArrayList<>();
        for(int i = start; i <= end; i++){
            if(isPrime(i)) results.add(i);
        }
        return results;
    }
}
线程池执行定时任务
/**
 * 线程池执行定时任务
 */
public class ScheduledPoolTs {
    public static void main(String[] args) {
        ScheduledExecutorService service = Executors.newScheduledThreadPool(4);
        service.scheduleAtFixedRate(()->{
            try {
                TimeUnit.MILLISECONDS.sleep(new Random().nextInt(1000));
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName());
        }, 0, 500, TimeUnit.MILLISECONDS);
    }
}
单个线程池
/**
 * 单个线程池,它的作用就是不管你创建几个线程,其实他们都是同一个线程。
 */
public class SingleThreadPoolTs {
    public static void main(String[] args) {
        ExecutorService service = Executors.newSingleThreadExecutor();
        for(int i = 0; i < 5; i++){
            final int j = i;
            service.execute(()->{
                System.out.println(j + " " + Thread.currentThread().getName());
            });
        }
    }
}
线程会主动找任务去做
/**
 * 这儿里的意思是线程会主动找任务去做
 */
public class WorkStealingPoolTs {
    public static void main(String[] args) throws IOException {
        ExecutorService service = Executors.newWorkStealingPool();
        System.out.println(Runtime.getRuntime().availableProcessors());

        service.execute(new R(1000));
        service.execute(new R(2000));
        service.execute(new R(2000));
        service.execute(new R(2000));
        service.execute(new R(2000));

        //由于产生的是精力线程(守护线程、后台线程),主线程不阻塞的话,看不到输出
        System.in.read();
    }
    static class R implements Runnable{
        int time;
        R(int t){
            this.time = t;
        }
        @Override
        public void run() {
            try {
                TimeUnit.MILLISECONDS.sleep(time);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(time + " " + Thread.currentThread().getName());
        }
    }
}

你可能感兴趣的:(Java)