【Java并发编程】01.Semaphore的使用

今天开始准备学习Java并发编程。准备把这个系列写到一个专栏里面,记录一下我学习Java并发编程的过程。希望和大家共同进步。

所有代码我会上传到GitHub上面,地址是:https://github.com/mrbcy/JavaConcurrentLearn

这个系列目前更新的部分是《Java并发编程核心方法与框架》的读书笔记。

Semaphore 的同步性

类Semaphore所提供的功能完全就是synchronized关键字的升级版,但它提供的功能更加的强大和方便,主要的作用是控制线程并发的数量。这一点单纯用synchronized是做不到的。

Semaphore发放许可的计算方式是“减法”操作。

public class Service {
    private Semaphore semaphore = new Semaphore(1);

    public void testMethod(){
        try {
            semaphore.acquire();
            System.out.println(Thread.currentThread().getName() + 
                    " begin timer=" + System.currentTimeMillis());

            Thread.sleep(5000);

            System.out.println(Thread.currentThread().getName() + 
                    " begin timer=" + System.currentTimeMillis());

            semaphore.release();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

Semaphore构造方法中的permit是许可的意思,代表同一时间内最多允许多少个线程同时执行acquire和release之间的代码。

acquire()方法代表使用一个许可,做减法操作。

下面我们同时启动几个线程,看一下Semaphore类是否能够控制住并发的数量。

TestThread.java

public class TestThread extends Thread{
    private Service service;

    public TestThread(Service service) {
        super();
        this.service = service;
    }

    @Override
    public void run() {
        super.run();

        service.testMethod();
    }


}

Run.java

package tech.mrbcy.javaconcurrentlearn.e01_1;

public class Run {
    public static void main(String[] args) {
        Service service = new Service();

        TestThread a = new TestThread(service);
        a.setName("A");

        TestThread b = new TestThread(service);
        b.setName("B");

        TestThread c = new TestThread(service);
        c.setName("C");

        a.start();
        b.start();
        c.start();
    }
}

输出的结果为:

A begin timer=1487347454779
A begin timer=1487347459780
B begin timer=1487347459780
B begin timer=1487347464781
C begin timer=1487347464781
C begin timer=1487347469781

可以看出只有一个线程同时执行。

如果把Service类中Semaphore的permit数量改成2,则会有下面的输出结果:

B begin timer=1487347739934
A begin timer=1487347739934
B end timer=1487347744934
A end timer=1487347744934
C begin timer=1487347744934
C end timer=1487347749935

permits值如果>1,不能保证线程安全,可能出现数据脏读。

动态添加permits

不只可以调用acquire方法和release来使用/释放1个许可,它们可以传入参数,一次性使用或释放多个许可。下面的代码动态的添加了多个permits:

package tech.mrbcy.javaconcurrentlearn.e01_2;

import java.util.concurrent.Semaphore;

public class Run {
    public static void main(String[] args) {
        try {
            Semaphore semaphore = new Semaphore(5);

            semaphore.acquire();
            semaphore.acquire();
            semaphore.acquire();
            semaphore.acquire();
            semaphore.acquire();
            System.out.println(semaphore.availablePermits());
            semaphore.release();
            semaphore.release();
            semaphore.release();
            semaphore.release();
            semaphore.release();
            semaphore.release();
            System.out.println(semaphore.availablePermits());
            semaphore.release(4);

            System.out.println(semaphore.availablePermits());
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

输出的结果是:

0
6
10

获取目前等待线程数

Service.java

package tech.mrbcy.javaconcurrentlearn.e01_3;

import java.util.concurrent.Semaphore;

public class Service {
    private Semaphore semaphore = new Semaphore(1);

    public void testMethod(){
        try {
            semaphore.acquire();
            Thread.sleep(1000);
            System.out.println("大约还有 " + semaphore.getQueueLength() + " 个线程在等待");
            System.out.println("是否有线程在等待信号量?" + semaphore.hasQueuedThreads());
        } catch (Exception e) {
            e.printStackTrace();
        } finally{
            semaphore.release();
        }
    }
}

TestThread.java

package tech.mrbcy.javaconcurrentlearn.e01_3;

public class TestThread extends Thread{
    private Service service;

    public TestThread(Service service) {
        super();
        this.service = service;
    }

    @Override
    public void run() {
        super.run();

        service.testMethod();
    }


}

Run.java

package tech.mrbcy.javaconcurrentlearn.e01_3;

public class Run {
    public static void main(String[] args) {
        Service service = new Service();

        TestThread firstThread = new TestThread(service);
        firstThread.start();

        TestThread[] threads = new TestThread[4];

        for(int i = 0; i < 4; i++){
            threads[i] = new TestThread(service);
            threads[i].start();
        }
    }
}

输出结果为:

大约还有 4 个线程在等待
是否有线程在等待信号量?true
大约还有 3 个线程在等待
是否有线程在等待信号量?true
大约还有 2 个线程在等待
是否有线程在等待信号量?true
大约还有 1 个线程在等待
是否有线程在等待信号量?true
大约还有 0 个线程在等待
是否有线程在等待信号量?false

公平信号量与非公平信号量

公平信号量是指先启动的线程一定会先获得锁。非公平信号量则没有这个限制。下面用代码来进行一下实验。

Service.java

package tech.mrbcy.javaconcurrentlearn.e01_4;

import java.util.concurrent.Semaphore;

public class Service {
    private boolean isFair = false;
    private Semaphore semaphore = new Semaphore(1, isFair);

    public void testMethod(){
        try {
            semaphore.acquire();
            System.out.println("ThreadName=" + Thread.currentThread().getName());

        } catch (Exception e) {
            e.printStackTrace();
        } finally{
            semaphore.release();
        }
    }
}

TestThread.java

package tech.mrbcy.javaconcurrentlearn.e01_4;

public class TestThread extends Thread{
    private Service service;

    public TestThread(Service service) {
        super();
        this.service = service;
    }

    @Override
    public void run() {
        super.run();
        System.out.println("ThreadName="+this.getName()+" 启动了!");
        service.testMethod();
    }


}

Run.java

package tech.mrbcy.javaconcurrentlearn.e01_4;

public class Run {
    public static void main(String[] args) {
        Service service = new Service();

        TestThread firstThread = new TestThread(service);
        firstThread.start();

        TestThread[] threads = new TestThread[4];

        for(int i = 0; i < 4; i++){
            threads[i] = new TestThread(service);
            threads[i].start();
        }
    }
}

运行结果:

ThreadName=Thread-1 启动了!
ThreadName=Thread-4 启动了!
ThreadName=Thread-0 启动了!
ThreadName=Thread-4
ThreadName=Thread-2 启动了!
ThreadName=Thread-2
ThreadName=Thread-0
ThreadName=Thread-3 启动了!
ThreadName=Thread-3
ThreadName=Thread-1

如果把Service的isFair改为true,则输出的结果变成:

ThreadName=Thread-2 启动了!
ThreadName=Thread-2
ThreadName=Thread-3 启动了!
ThreadName=Thread-3
ThreadName=Thread-0 启动了!
ThreadName=Thread-4 启动了!
ThreadName=Thread-1 启动了!
ThreadName=Thread-0
ThreadName=Thread-4
ThreadName=Thread-1

多进路-多处理-多出路实验

本实验的目标是允许多个线程同时处理任务,更具体的来说,就是每个线程都在处理自己的任务。

Service.java

package tech.mrbcy.javaconcurrentlearn.e01_5;

import java.util.concurrent.Semaphore;

public class Service {
    private Semaphore semaphore = new Semaphore(3);

    public void testMethod(){
        try {
            semaphore.acquire();
            System.out.println("ThreadName=" + Thread.currentThread().getName() + " 准备");
            System.out.println("begin hello " + System.currentTimeMillis());

            for(int i = 0; i < 5; i++){
                System.out.println("ThreadName=" + Thread.currentThread().getName() + " 打印" + (i+1));
            }

            System.out.println("end hello " + System.currentTimeMillis());
            semaphore.release();
            System.out.println("ThreadName=" + Thread.currentThread().getName() + " 结束");
        } catch (Exception e) {
            e.printStackTrace();
        } finally{

        }
    }
}

TestThread.java

package tech.mrbcy.javaconcurrentlearn.e01_5;

public class TestThread extends Thread{
    private Service service;

    public TestThread(Service service) {
        super();
        this.service = service;
    }

    @Override
    public void run() {
        super.run();
        service.testMethod();
    }


}

Run.java

package tech.mrbcy.javaconcurrentlearn.e01_5;

public class Run {
    public static void main(String[] args) {
        Service service = new Service();


        TestThread[] threads = new TestThread[12];

        for(int i = 0; i < threads.length; i++){
            threads[i] = new TestThread(service);
            threads[i].start();
        }
    }
}

运行结果如下:

ThreadName=Thread-2 准备
ThreadName=Thread-1 准备
ThreadName=Thread-0 准备
begin hello 1487433434952
begin hello 1487433434952
ThreadName=Thread-1 打印1
begin hello 1487433434952
ThreadName=Thread-1 打印2
ThreadName=Thread-2 打印1
ThreadName=Thread-1 打印3
ThreadName=Thread-0 打印1
ThreadName=Thread-1 打印4
ThreadName=Thread-1 打印5
end hello 1487433434953
ThreadName=Thread-2 打印2
ThreadName=Thread-3 准备
begin hello 1487433434953
ThreadName=Thread-3 打印1
ThreadName=Thread-1 结束
ThreadName=Thread-0 打印2
ThreadName=Thread-3 打印2
ThreadName=Thread-2 打印3
ThreadName=Thread-3 打印3
ThreadName=Thread-3 打印4
ThreadName=Thread-0 打印3
ThreadName=Thread-3 打印5
ThreadName=Thread-2 打印4
end hello 1487433434955
ThreadName=Thread-0 打印4
ThreadName=Thread-3 结束
ThreadName=Thread-2 打印5
ThreadName=Thread-0 打印5
ThreadName=Thread-4 准备
end hello 1487433434955
ThreadName=Thread-0 结束
end hello 1487433434955
ThreadName=Thread-6 准备
ThreadName=Thread-7 准备
begin hello 1487433434956
ThreadName=Thread-7 打印1
ThreadName=Thread-7 打印2
begin hello 1487433434955
ThreadName=Thread-7 打印3
begin hello 1487433434956
ThreadName=Thread-6 打印1
ThreadName=Thread-6 打印2
ThreadName=Thread-6 打印3
ThreadName=Thread-6 打印4
ThreadName=Thread-2 结束
ThreadName=Thread-6 打印5
ThreadName=Thread-7 打印4
ThreadName=Thread-7 打印5
ThreadName=Thread-4 打印1
end hello 1487433434956
end hello 1487433434956
ThreadName=Thread-7 结束
ThreadName=Thread-4 打印2
ThreadName=Thread-8 准备
ThreadName=Thread-6 结束
begin hello 1487433434956
ThreadName=Thread-5 准备
begin hello 1487433434957
ThreadName=Thread-5 打印1
ThreadName=Thread-4 打印3
ThreadName=Thread-5 打印2
ThreadName=Thread-5 打印3
ThreadName=Thread-5 打印4
ThreadName=Thread-5 打印5
end hello 1487433434957
ThreadName=Thread-5 结束
ThreadName=Thread-8 打印1
ThreadName=Thread-9 准备
begin hello 1487433434957
ThreadName=Thread-4 打印4
ThreadName=Thread-9 打印1
ThreadName=Thread-9 打印2
ThreadName=Thread-9 打印3
ThreadName=Thread-8 打印2
ThreadName=Thread-8 打印3
ThreadName=Thread-9 打印4
ThreadName=Thread-4 打印5
ThreadName=Thread-9 打印5
ThreadName=Thread-8 打印4
ThreadName=Thread-8 打印5
end hello 1487433434957
end hello 1487433434957
ThreadName=Thread-10 准备
begin hello 1487433434957
ThreadName=Thread-10 打印1
ThreadName=Thread-10 打印2
ThreadName=Thread-9 结束
end hello 1487433434957
ThreadName=Thread-10 打印3
ThreadName=Thread-4 结束
ThreadName=Thread-11 准备
ThreadName=Thread-10 打印4
ThreadName=Thread-8 结束
ThreadName=Thread-10 打印5
end hello 1487433434959
begin hello 1487433434959
ThreadName=Thread-10 结束
ThreadName=Thread-11 打印1
ThreadName=Thread-11 打印2
ThreadName=Thread-11 打印3
ThreadName=Thread-11 打印4
ThreadName=Thread-11 打印5
end hello 1487433434960
ThreadName=Thread-11 结束

可以看出有多个线程在同时运行。

多进路-单处理-多出路实验

这个实验是在上面的多进路-多处理-多出路实验基础上稍加修改的。目标是允许多个线程同时处理任务,但执行任务的顺序缺是同步的,也就是阻塞的,所以称为单处理。

Service.java

package tech.mrbcy.javaconcurrentlearn.e01_6;

import java.util.concurrent.Semaphore;
import java.util.concurrent.locks.ReentrantLock;


public class Service {
    private Semaphore semaphore = new Semaphore(3);
    private ReentrantLock lock = new ReentrantLock();

    public void testMethod(){
        try {
            semaphore.acquire();
            System.out.println("ThreadName=" + Thread.currentThread().getName() + " 准备");
            lock.lock();
            System.out.println("begin hello " + System.currentTimeMillis());

            for(int i = 0; i < 5; i++){
                System.out.println("ThreadName=" + Thread.currentThread().getName() + " 打印" + (i+1));
            }

            System.out.println("end hello " + System.currentTimeMillis());
            lock.unlock();
            semaphore.release();
            System.out.println("ThreadName=" + Thread.currentThread().getName() + " 结束");
        } catch (Exception e) {
            e.printStackTrace();
        } finally{

        }
    }
}

其他都没有变化。

输出结果如下:

ThreadName=Thread-1 准备
ThreadName=Thread-0 准备
ThreadName=Thread-2 准备
begin hello 1487433927769
ThreadName=Thread-1 打印1
ThreadName=Thread-1 打印2
ThreadName=Thread-1 打印3
ThreadName=Thread-1 打印4
ThreadName=Thread-1 打印5
end hello 1487433927769
ThreadName=Thread-11 准备
begin hello 1487433927769
ThreadName=Thread-1 结束
ThreadName=Thread-0 打印1
ThreadName=Thread-0 打印2
ThreadName=Thread-0 打印3
ThreadName=Thread-0 打印4
ThreadName=Thread-0 打印5
end hello 1487433927770
ThreadName=Thread-0 结束
ThreadName=Thread-3 准备
begin hello 1487433927770
ThreadName=Thread-2 打印1
ThreadName=Thread-2 打印2
ThreadName=Thread-2 打印3
ThreadName=Thread-2 打印4
ThreadName=Thread-2 打印5
end hello 1487433927771
ThreadName=Thread-2 结束
ThreadName=Thread-4 准备
begin hello 1487433927771
ThreadName=Thread-11 打印1
ThreadName=Thread-11 打印2
ThreadName=Thread-11 打印3
ThreadName=Thread-11 打印4
ThreadName=Thread-11 打印5
end hello 1487433927771
ThreadName=Thread-11 结束
ThreadName=Thread-5 准备
begin hello 1487433927771
ThreadName=Thread-3 打印1
ThreadName=Thread-3 打印2
ThreadName=Thread-3 打印3
ThreadName=Thread-3 打印4
ThreadName=Thread-3 打印5
end hello 1487433927772
ThreadName=Thread-3 结束
ThreadName=Thread-6 准备
begin hello 1487433927772
ThreadName=Thread-4 打印1
ThreadName=Thread-4 打印2
ThreadName=Thread-4 打印3
ThreadName=Thread-4 打印4
ThreadName=Thread-4 打印5
end hello 1487433927772
ThreadName=Thread-4 结束
begin hello 1487433927772
ThreadName=Thread-7 准备
ThreadName=Thread-5 打印1
ThreadName=Thread-5 打印2
ThreadName=Thread-5 打印3
ThreadName=Thread-5 打印4
ThreadName=Thread-5 打印5
end hello 1487433927772
ThreadName=Thread-5 结束
begin hello 1487433927772
ThreadName=Thread-9 准备
ThreadName=Thread-6 打印1
ThreadName=Thread-6 打印2
ThreadName=Thread-6 打印3
ThreadName=Thread-6 打印4
ThreadName=Thread-6 打印5
end hello 1487433927772
ThreadName=Thread-6 结束
ThreadName=Thread-8 准备
begin hello 1487433927773
ThreadName=Thread-7 打印1
ThreadName=Thread-7 打印2
ThreadName=Thread-7 打印3
ThreadName=Thread-7 打印4
ThreadName=Thread-7 打印5
end hello 1487433927773
ThreadName=Thread-7 结束
ThreadName=Thread-10 准备
begin hello 1487433927773
ThreadName=Thread-9 打印1
ThreadName=Thread-9 打印2
ThreadName=Thread-9 打印3
ThreadName=Thread-9 打印4
ThreadName=Thread-9 打印5
end hello 1487433927773
ThreadName=Thread-9 结束
begin hello 1487433927773
ThreadName=Thread-8 打印1
ThreadName=Thread-8 打印2
ThreadName=Thread-8 打印3
ThreadName=Thread-8 打印4
ThreadName=Thread-8 打印5
end hello 1487433927773
ThreadName=Thread-8 结束
begin hello 1487433927773
ThreadName=Thread-10 打印1
ThreadName=Thread-10 打印2
ThreadName=Thread-10 打印3
ThreadName=Thread-10 打印4
ThreadName=Thread-10 打印5
end hello 1487433927773
ThreadName=Thread-10 结束

使用Semaphore创建字符串池

这个demo涉及到了一个新的概念:Condition。详细的说明可以参考http://ifeve.com/understand-condition/

ListPool.java

package tech.mrbcy.javaconcurrentlearn.e01_7;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Semaphore;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;

/**
 * Condition 可以参考http://ifeve.com/understand-condition/
 * @author mrbcy
 *
 */
public class ListPool {
    private int poolMaxSize = 3;
    private int semaphorePermits = 5;
    private List<String> list = new ArrayList<String>();
    private Semaphore concurrencySemaphore = new Semaphore(semaphorePermits);
    private ReentrantLock lock = new ReentrantLock();
    private Condition condition = lock.newCondition();

    public ListPool(){
        for (int i=0; i < poolMaxSize; i++){
            list.add(" mrbcy " + (i + 1));
        }
    }

    public String get(){
        String getString = null;
        try {
            concurrencySemaphore.acquire();
            lock.lock();
            while(list.size() == 0){
                condition.await();
            }
            getString = list.remove(0);
            lock.unlock();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return getString;
    }

    public void put(String stringValue){
        lock.lock();
        list.add(stringValue);
        condition.signalAll();
        lock.unlock();
        concurrencySemaphore.release();
    }
}

MyThread.java

package tech.mrbcy.javaconcurrentlearn.e01_7;

public class MyThread extends Thread{
    private ListPool listPool;

    public MyThread(ListPool listPool) {
        super();
        this.listPool = listPool;
    }

    @Override
    public void run() {
        super.run();

        for(int i = 0; i < Integer.MAX_VALUE; i++){
            String getString = listPool.get();
            System.out.println(Thread.currentThread().getName() + " 取得值 " 
                    + getString);
            listPool.put(getString);
        }
    }


}

Run.java

package tech.mrbcy.javaconcurrentlearn.e01_7;

public class Run {
    public static void main(String[] args) {
        ListPool listPool = new ListPool();


        MyThread[] threads = new MyThread[12];

        for(int i = 0; i < threads.length; i++){
            threads[i] = new MyThread(listPool);
            threads[i].start();
        }
    }
}

运行结果:

Thread-9 取得值  mrbcy 2
Thread-9 取得值  mrbcy 2
Thread-9 取得值  mrbcy 2
Thread-9 取得值  mrbcy 2
Thread-9 取得值  mrbcy 2
Thread-9 取得值  mrbcy 2
Thread-10 取得值  mrbcy 2
Thread-3 取得值  mrbcy 3
Thread-10 取得值  mrbcy 2
Thread-10 取得值  mrbcy 2
Thread-10 取得值  mrbcy 2
Thread-10 取得值  mrbcy 2
Thread-10 取得值  mrbcy 2
Thread-7 取得值  mrbcy 2
Thread-4 取得值  mrbcy 1
Thread-4 取得值  mrbcy 1
Thread-4 取得值  mrbcy 1
Thread-4 取得值  mrbcy 1
Thread-4 取得值  mrbcy 1
Thread-9 取得值  mrbcy 1
Thread-9 取得值  mrbcy 1
Thread-4 取得值  mrbcy 1
Thread-4 取得值  mrbcy 1
Thread-10 取得值  mrbcy 1
Thread-10 取得值  mrbcy 1
Thread-9 取得值  mrbcy 1
Thread-7 取得值  mrbcy 2
Thread-4 取得值  mrbcy 2
Thread-3 取得值  mrbcy 3
Thread-10 取得值  mrbcy 3
Thread-4 取得值  mrbcy 2
Thread-7 取得值  mrbcy 2
Thread-7 取得值  mrbcy 2
Thread-3 取得值  mrbcy 2
Thread-3 取得值  mrbcy 2
Thread-4 取得值  mrbcy 2
Thread-9 取得值  mrbcy 1
Thread-9 取得值  mrbcy 1
Thread-4 取得值  mrbcy 2
Thread-10 取得值  mrbcy 3
Thread-4 取得值  mrbcy 2

Semaphore多生产者多消费者实验

本实验的目的不光是实现生产者与消费者模式,还要限制生产者与消费者的数量。

RepastService.java

package tech.mrbcy.javaconcurrentlearn.e01_8;

import java.util.concurrent.Semaphore;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;


public class RepastService {
    volatile private Semaphore setSemaphore = new Semaphore(10); // 生产者
    volatile private Semaphore getSemaphore = new Semaphore(20); // 消费者
    volatile private ReentrantLock lock = new ReentrantLock();
    volatile private Condition setCondition = lock.newCondition();
    volatile private Condition getCondition = lock.newCondition();
    // 暂存产品,只能有4个
    volatile private Object[] produceShelf = new Object[4];

    private boolean isEmpty() {
        boolean isEmpty = true;
        for(int i = 0; i < produceShelf.length; i++){
            if(produceShelf[i] != null){
                isEmpty = false;
                break;
            }
        }

        return isEmpty;
    }

    private boolean isFull() {
        boolean isFull = true;
        for(int i = 0; i < produceShelf.length; i++){
            if(produceShelf[i] == null){
                isFull = false;
                break;
            }
        }
        return isFull;
    }

    public void set() {
        try {
            setSemaphore.acquire();
            lock.lock();

            while(isFull()){
                setCondition.await();
            }

            for(int i = 0; i < produceShelf.length; i++){
                if(produceShelf[i] == null){
                    produceShelf[i] = "数据";
                    System.out.println(Thread.currentThread().getName() 
                            + " 生产了 " + produceShelf[i]);
                    break;
                }
            }

            getCondition.signalAll();
            lock.unlock();
        } catch (Exception e) {
            e.printStackTrace();
        }finally{
            setSemaphore.release();
        }

    }

    public void get() {
        try {
            getSemaphore.acquire();
            lock.lock();
            while (isEmpty()){
                getCondition.await();
            }

            for(int i = 0; i < produceShelf.length; i++){
                if(produceShelf[i] != null){
                    System.out.println(Thread.currentThread().getName() 
                            + " 消费了 " + produceShelf[i]);
                    produceShelf[i] = null;
                    break;
                }
            }

            setCondition.signalAll();
            lock.unlock();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            getSemaphore.release();
        }
    }
}

ThreadC.java

package tech.mrbcy.javaconcurrentlearn.e01_8;

public class ThreadC extends Thread{

    private RepastService service;

    public ThreadC(RepastService service) {
        super();
        this.service = service;
    }

    @Override
    public void run() {
        super.run();
        service.get();
    }



}

ThreadP.java

package tech.mrbcy.javaconcurrentlearn.e01_8;

public class ThreadP extends Thread{

    private RepastService service;

    public ThreadP(RepastService service) {
        super();
        this.service = service;
    }

    @Override
    public void run() {
        super.run();
        service.set();
    }



}

Run.java

package tech.mrbcy.javaconcurrentlearn.e01_8;

public class Run {
    public static void main(String[] args) throws InterruptedException {
        RepastService service = new RepastService();

        ThreadP[] threadPs = new ThreadP[60];
        ThreadC[] threadCs = new ThreadC[60];

        for(int i = 0; i < 60; i++){
            threadPs[i] = new ThreadP(service);
            threadCs[i] = new ThreadC(service);
        }

        Thread.sleep(2000);

        for(int i = 0; i < 60; i++){
            threadPs[i].start();
            threadCs[i].start();
        }
    }
}

运行结果:

Thread-0 生产了 数据
Thread-8 生产了 数据
Thread-9 消费了 数据
Thread-1 消费了 数据
Thread-12 生产了 数据
Thread-13 消费了 数据
Thread-2 生产了 数据
Thread-18 生产了 数据
Thread-23 消费了 数据
Thread-19 消费了 数据
Thread-20 生产了 数据
Thread-3 消费了 数据
Thread-4 生产了 数据
Thread-6 生产了 数据
Thread-28 生产了 数据
Thread-5 消费了 数据
Thread-36 生产了 数据
Thread-37 消费了 数据
Thread-41 消费了 数据
Thread-11 消费了 数据
Thread-10 生产了 数据
Thread-7 消费了 数据
Thread-14 生产了 数据
Thread-16 生产了 数据
Thread-54 生产了 数据
Thread-15 消费了 数据
Thread-61 消费了 数据
Thread-63 消费了 数据
Thread-24 生产了 数据
Thread-42 生产了 数据
Thread-25 消费了 数据
Thread-67 消费了 数据
Thread-22 生产了 数据
Thread-71 消费了 数据
Thread-30 生产了 数据
Thread-73 消费了 数据
Thread-26 生产了 数据
Thread-31 消费了 数据
Thread-32 生产了 数据
Thread-33 消费了 数据
Thread-38 生产了 数据
Thread-89 消费了 数据
Thread-40 生产了 数据
Thread-39 消费了 数据
Thread-34 生产了 数据
Thread-55 消费了 数据
Thread-94 生产了 数据
Thread-100 生产了 数据
Thread-59 消费了 数据
Thread-58 生产了 数据
Thread-109 消费了 数据
Thread-60 生产了 数据
Thread-110 生产了 数据
Thread-112 生产了 数据
Thread-57 消费了 数据
Thread-44 生产了 数据
Thread-117 消费了 数据
Thread-69 消费了 数据
Thread-119 消费了 数据
Thread-87 消费了 数据
Thread-46 生产了 数据
Thread-21 消费了 数据
Thread-74 生产了 数据
Thread-68 生产了 数据
Thread-27 消费了 数据
Thread-29 消费了 数据
Thread-52 生产了 数据
Thread-75 消费了 数据
Thread-50 生产了 数据
Thread-78 生产了 数据
Thread-76 生产了 数据
Thread-80 生产了 数据
Thread-77 消费了 数据
Thread-48 生产了 数据
Thread-35 消费了 数据
Thread-56 生产了 数据
Thread-45 消费了 数据
Thread-81 消费了 数据
Thread-43 消费了 数据
Thread-53 消费了 数据
Thread-62 生产了 数据
Thread-114 生产了 数据
Thread-116 生产了 数据
Thread-64 生产了 数据
Thread-85 消费了 数据
Thread-91 消费了 数据
Thread-93 消费了 数据
Thread-65 消费了 数据
Thread-66 生产了 数据
Thread-104 生产了 数据
Thread-98 生产了 数据
Thread-95 消费了 数据
Thread-17 消费了 数据
Thread-70 生产了 数据
Thread-106 生产了 数据
Thread-97 消费了 数据
Thread-79 消费了 数据
Thread-101 消费了 数据
Thread-72 生产了 数据
Thread-103 消费了 数据
Thread-82 生产了 数据
Thread-99 消费了 数据
Thread-84 生产了 数据
Thread-105 消费了 数据
Thread-86 生产了 数据
Thread-107 消费了 数据
Thread-90 生产了 数据
Thread-88 生产了 数据
Thread-92 生产了 数据
Thread-96 生产了 数据
Thread-111 消费了 数据
Thread-113 消费了 数据
Thread-51 消费了 数据
Thread-115 消费了 数据
Thread-102 生产了 数据
Thread-108 生产了 数据
Thread-118 生产了 数据
Thread-49 消费了 数据
Thread-47 消费了 数据
Thread-83 消费了 数据

总结

这篇博客主要使用了Semaphore类提供的各种方法,还用字符串池以及生产者消费者的例子进行了综合的应用。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值