博客
关于我
21 并发
阅读量:730 次
发布时间:2019-03-21

本文共 5417 字,大约阅读时间需要 18 分钟。

基本线程机制及并发编程

线程在计算机编程中扮演着至关重要的角色。通过创建和管理线程,程序能够同时执行多项任务,提升效率。在本章中,我们将探索线程的基础机制,了解如何在Java中实现任务调度以及如何处理共享资源的竞争与死锁问题。

定义任务

线程可以通过Runnable接口定义任务,实现run()方法即可。Runnable对象可以随时由Thread类或Executor服务运行。例如,LiftOff类通过实现Runnable接口,定义了一个倒计时任务:

class LiftOff implements Runnable {    protected int countDown = 10;    private static int taskCount = 0;    private final int id = taskCount++;    @Override    public void run() {        System.out.println("Thread:" + Thread.currentThread());        while (countDown > 0) {            System.out.println(status());        }    }    private String status() {        return "#" + id + "(" + countDown + ")" + " ";    }}

Thread类

Thread类是Java中线程的核心,它通过构造器接受一个Runnable对象。调用start()方法启动线程运行,自动调用Runnablerun()方法。例如,使用BasicThreads类创建并启动线程:

class BasicThreads {    public static void chapter21_2() {        System.out.println("BasicThreads:" + Thread.currentThread());        Thread t = new Thread(new LiftOff());        t.start();    }}

Executor服务

java.util.concurrent包中,Executor服务提供了更高级的线程管理功能。CachedThreadPool默认创建新的线程执行任务,与FternalThreadSingleThreadExecutor形成了不同策略的选择。

class CachedThreadPool {    public static void chapter21_2() {        System.out.println("CachedThreadPool:" + Thread.currentThread());        ExecutorService executorService = Executors.newCachedThreadPool();        for (int i = 0; i < 3; i++) {            executorService.execute(new LiftOff());        }        executorService.shutdown();    }}

任务返回值

若任务完成后需返回值,可以实现Callable接口。Callable支持异步计算,通过Future获取结果。

class CallableDemo {    public static void chapter21_2() {        ExecutorService executorService = Executors.newCachedThreadPool();        ArrayList
> results = new ArrayList<>(); for (int i = 0; i < 3; i++) { results.add(executorService.submit(new TaskWithResult(i))); } for (Future
fs : results) { try { System.out.println(fs.get()); } catch (InterruptedException | ExecutionException e) { e.printStackTrace(); } } }}

共享资源的竞争与互斥

在多线程环境下,共享资源可能引发竞争,导致逻辑错误。通过synchronize关键字实现方法同步,确保一种线程 一定在执行时占据资源。例如,SynchronizedEvenGenerator确保多个线程仅按顺序访问资源。

abstract class IntGenerator {    public abstract int next();}class SynchronizedEvenGenerator extends IntGenerator {    private int currentValue = 0;    @Override    public synchronized int next() {        currentValue++;        currentValue++;        return currentValue;    }}

Thread中的等待与通知

线程间通过wait()notify()方法进行等待与唤醒。wait()使线程挂起,直到notify()notifyAll()被调用。例如,在WaxOMatic中,WaxOnWaxOff任务通过condition实现等待与唤醒。

class WaxOMatic {    public static void chapter21_5() {        Car car = new Car();        ExecutorService executorService = Executors.newCachedThreadPool();        executorService.execute(new WaxOff(car));        executorService.execute(new WaxOn(car));        try {            TimeUnit.MILLISECONDS.sleep(1000);        } catch (InterruptedException e) {            e.printStackTrace();        }        executorService.shutdownNow();    }}

Deadlock 死锁处理

正確解決哲學家問題,需调整拿取顺序。如FixedDiningPhilosophers,让最后一个哲学家先拿左筷子,解决死锁。

class FixedDiningPhilosophers {    public static void chapter21_6() throws InterruptedException {        int ponder = 3;        int size = 2;        ExecutorService executorService = Executors.newCachedThreadPool();        Chopstick[] chopsticks = new Chopstick[size];        for (int i = 0; i < size; i++) {            Chopstick chopstick = new Chopstick();            Chopsticks[i] = chopstick;        }        for (int i = 0; i < size; i++) {            Runnable run = () -> {                try {                    while (!Thread.interrupted()) {                        right.take();                        left.take();                    }                } catch (InterruptedException e) {                    e.printStackTrace();                }                System.out.println("philosopher " + i + " done");            };            executorService.execute(run);        }        TimeUnit.SECONDS.sleep(3);        for (int i = 0; i < size; i++) {            Chopstick left = Chopsticks[i];            Chopstick right = Chopsticks[(i + 1) % size];            left.drop();            right.drop();        }    }}

性能优化与可扩展性

通过比较LockSynchronized的性能差异,选择合适的互斥机制。同时,利用ConcurrentHashMapCopyOnWriteArrayList等高效容器,确保线程安全与性能并存。

class ConcurrentHashMapExample {    public static void chapter21_9() {        ConcurrentHashMap
map = new ConcurrentHashMap(); map.put("key1", 100); map.put("key2", 200); System.out.println(map.get("key1"));//100 System.out.println(map.size());//2 map Put "key3", 300 map remove"key1", 200 map.get("key1")//200 System.out.println(map.size())//3 }}

未来任务

通过ActiveObjectDemo展示活动对象的特点,实现任务的串行化与资源管理。这种模式允许任务在多线程环境下无缝衔接,提升整体效率。

class ActiveObjectDemo {    private ExecutorService executorService = Executors.newSingleThreadExecutor();    public Future
calculateInt(int x, int y) { return executorService.submit(() -> { System.out.println("starting " + x + " + " + y); try { TimeUnit.MILLISECONDS.sleep(200); return x + y; } catch (InterruptedException e) { e.printStackTrace(); } }); } public void shutdown() { executorService.shutdown(); }}

通过以上方法和实例,可以全面理解线程机制,掌握解决多线程编程问题的关键策略。

转载地址:http://okdgz.baihongyu.com/

你可能感兴趣的文章
Openlayers中实现地图上添加一条红色直线
查看>>
Openlayers中将某个feature置于最上层
查看>>
Openlayers中点击地图获取坐标并输出
查看>>
Openlayers中设置定时绘制和清理直线图层
查看>>
Openlayers入门教程 --- 万字长篇
查看>>
Openlayers图文版实战,vue项目从0到1做基础配置
查看>>
OpenLayers学习三:地图旋转及地图跳转到某一点的方式(以类为接口)
查看>>
Openlayers实战:loadstart和loadend事件
查看>>
Openlayers实战:modifystart、modifyend互动示例
查看>>
Openlayers实战:moveend事件,利用calculateExtent获取地图左上和右下的坐标
查看>>
Openlayers实战:判断共享单车是否在电子围栏内
查看>>
Openlayers实战:利用turf获取两个多边形的交集、差集、并集
查看>>
Openlayers实战:加载Bing地图
查看>>
Openlayers实战:加载GeoJSON
查看>>
Openlayers实战:加载SHP文件
查看>>
Openlayers实战:界面控制综合演示
查看>>
Openlayers实战:绘制图形,导出geojson文件
查看>>
Openlayers实战:绘制图形,导出KML文件
查看>>
Openlayers实战:绘制多边形,导出CSV文件
查看>>
Openlayers实战:绘制带箭头的线
查看>>