ku链接的核心专题:酷游网址与Java 的并行程式设计案例

本文由 ku链接 вт989点сс 酷游网址编译执行,任务简介为学习Java Concurrency,并以经典的生产者消费者问题作为探讨案例。

TODO: 学习Java Concurrency

列出Java 并行的各式基础建设,解释thread, thread pool, memory consistency,

synchronized,java.util.concurrent套件(至少要提及Executor 和fork/join 模式), deadlock vs. livelock, immutable, lock 等议题,适度提供范例程式码(要改写,不同于Oracle 提供的范例)。

Thread
Thread是一个在java.lang内的一种物件,他可以在Java 中建立额外的执行绪执行程式码。使Java 具并行程式设计的特质。

在实作中,有以下两种常见的实作方法:

继承Thread这个物件

class SendDataToSevrver extends Thread {
    String JSON;
    
    public SendDataToServer(String JSON) {
        this.JSON = JSON;
    }
    
    public void run() {
        sendData(JSON);
    }
}

class MAIN() {
    public static void main(String[] args) {
        String JSON = "{\"name\":\"zack\"}";
        SendDataToServer s = new SendDataToServer(JSON);
        s.start();
    }
}

实作Runnable介面,在藉由Thread执行

class SendDataToServer implements Runnable {
    String JSON;
    
    public SendDataToServer(String JSON) {
        this.JSON = JSON;
    }
    
    public void run() {
        sendData(JSON);
    }
}

class MAIN() {
    public static void main(String[] args) {
        String JSON = "{\"name\":\"zack\"}";
        Thread t0 = new Thread(new SendDataToServer(JSON));
        t0.start();
    }
}

在实作中,两者最大的差异就是前者不能再继承其他物件了,而后者除了可以继承其他物件,还可以实作其他介面。因此,通常是以Runnable介面实作居多。
留言

值得注意的是,同一个实作Runnable介面的物件,是可以同时被多个Thread执行的,且有些变数是可以互通的,但也可能带来一些问题,如抢占。范例程式码如下:

ThreadPool
在现实世界的问题中,许多运算并不是能完全平行的,都需要等待其他执行绪完成到一个段落才能继续进行,也就是说并不是创建愈多执行绪速度就可以更快。再加上创建一个新的Thread需要相当的记忆体,所以一般实作中不会开到太多的执行绪。

延续前一部分,我们知道实作Runnable介面的物件可以被执行绪执行,那这样是不是就可以把诸多个想要平行处理的任务分到多个实作Runnable介面的物件,而让一定数量的执行绪执行这些物件。这么做不仅可以减少开立Thread的记忆体开销,还可以提升执行续的运算效率,以尽量塞满每个执行绪。

而放这些待执行物件的地方就是ThreadPool。另外,这里除了可以放Runnable 的物件,也可以放Callable的物件。

memory consistency
Java 的Memory model 如下图,每个执行绪会有自己一个快取空间放置自己的local object ;但若要与其他执行续共享物件,则要把物件存于堆积(heap)中。

以下图为例,倘若A 执行绪要存取物件O ,那物件O 会经过A 快取再到A 执行绪,最后A 执行绪在经由A 快取写入堆积(Heap)。这段过程是需要一定时间的。因此,若B 执行绪同时也要存取物件O ,那变可能会发生抢占的问题,造成运算出非预期的结果。

为解决这个问题,我们就要使用synchronized或lock 来解决抢占的问题。

synchronized
synchronized这个关键字会限制只能有一个执行绪在存取物件或使用物件中的synchronized方法,这可以避免并行程式设计中抢占的情况发生。

在Java 的术语,是method (方法),而非function (函式)

synchronized block
下列为synchronized block的程式范例。若以下列方式撰写,synchronized就会限制在同一时间只能有一个执行绪存取count这个变数,最后count应为2 。若没有加上synchronized,因可能两个执行绪同十加1 而造成抢占的问题,count则有可能是1 。

class Counter implements Runnable {
    int count;
    
    Counter(int count) {
        this.count = count;
    }
    
    public Run() {
        synchronized(count) { count++; }
    }
    
    public int getCount() { return count; }
}

class MAIN () {
    public static void (String[] args) {
        Counter counter = new Counter(0);
        
        Thread t0 = new Thread(counter);
        Thread t1 = new Thread(counter);
        
        System.out.println(counter.getCount());
    }
}

synchronized method

class Counter implements Runnable {
    int count;
    
    Counter(int count) {
        this.count = count;
    }
    
    public Run() {
        countIncrement();
        countIncrement();
    }
    
    public synchronized void countIncrement() {
        count++;
    }
    
    public int getCount() { return count; }
}

class MAIN () {
    public static void (String[] args) {
        Counter counter = new Counter(0);
        
        Thread t0 = new Thread(counter);
        Thread t1 = new Thread(counter);
        
        System.out.println(counter.getCount());
    }
}

  • 16
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值