用synchronized实现Semaphore
Posted zhujm320
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了用synchronized实现Semaphore相关的知识,希望对你有一定的参考价值。
介绍
基于Semaphore的功能,主要用来实现并发和限流,本文采用synchronized来实现Semaphore基础功能。关于Semaphore的说明,请参考JDK1.8 信号量(Semaphore)的基本使用
代码实现
public class MySemaphore {
private volatile int count;
private volatile int waitCount = 0;
/**
* 初始化信号量
* @param count
*/
public MySemaphore(int count) {
this.count = count;
}
/**
* 获取信号量
* @throws InterruptedException
*/
public void acquire() throws InterruptedException {
while (true) {
//大量线程在此处等锁
//执行wait的线程被唤醒后, 重新加入抢锁操作
waitCount++;
synchronized (this) {
if (this.count > 0) {
this.count--;
waitCount--;
break;
}
this.wait();
}
waitCount--;
//退出synchronized代码块,释放锁
}
}
/**
* 释放锁,通知所有等待线程进行抢锁
*/
public void release() {
synchronized (this) {
this.count++;
this.notifyAll();
}
}
/**
* 可用的信号量
* @return
*/
public int availablePermits(){
return this.count;
}
/**
* 阻塞线程的个数
* @return
*/
public int getQueueLength(){
return waitCount;
}
}
上述代码主要实现了acquire(),release(),availablePermits()和getQueueLength()最基础的功能。
测试代码
package sample;
import java.util.concurrent.Semaphore;
public class SemaphoreTest {
public static void main(String[] args) {
// Semaphore semaphore=new Semaphore(24);
MySemaphore semaphore = new MySemaphore(24);
// int count = semaphore.availablePermits();
// System.out.println("可用信号量 count1: " + count);
// //增加20个信号量
// semaphore.release(20);
int count = semaphore.availablePermits();
//此时信号量个数为24个, 可以支持同时跑24个线程
System.out.println("可用信号量 count2: " + count);
for (int i = 0; i < 200; i ++){
new Thread(()->{
try {
semaphore.acquire();
System.out.println("" + Thread.currentThread().getName() + " 进入" + " 时间: " + System.currentTimeMillis());
Thread.sleep(200);
System.out.println("" + Thread.currentThread().getName() + " 退出" + " 时间: " + System.currentTimeMillis());
semaphore.release();
} catch (InterruptedException e) {
e.printStackTrace();
}
}, "线程"+i).start();
}
//延迟一下等待获取信号量的线程全部进入等待队列
try{
Thread.sleep(10);
}catch (Exception e){
e.printStackTrace();
}
int waitT = semaphore.getQueueLength();
System.out.println("等待线程个数: " + waitT + " 时间: " + System.currentTimeMillis());
}
}
测试结果
可用信号量 count2: 24
线程0 进入 时间: 1621162349849
线程3 进入 时间: 1621162349849
线程6 进入 时间: 1621162349850
线程1 进入 时间: 1621162349850
线程4 进入 时间: 1621162349850
线程9 进入 时间: 1621162349850
线程2 进入 时间: 1621162349850
线程16 进入 时间: 1621162349850
线程8 进入 时间: 1621162349851
线程10 进入 时间: 1621162349851
线程25 进入 时间: 1621162349851
线程5 进入 时间: 1621162349851
线程29 进入 时间: 1621162349851
线程31 进入 时间: 1621162349851
线程33 进入 时间: 1621162349851
线程15 进入 时间: 1621162349851
线程7 进入 时间: 1621162349851
线程17 进入 时间: 1621162349851
线程39 进入 时间: 1621162349852
线程18 进入 时间: 1621162349852
线程20 进入 时间: 1621162349852
线程21 进入 时间: 1621162349852
线程22 进入 时间: 1621162349855
线程23 进入 时间: 1621162349855
等待线程个数: 176 时间: 1621162349885
线程20 退出 时间: 1621162350059
线程5 退出 时间: 1621162350059
线程22 退出 时间: 1621162350059
线程0 退出 时间: 1621162350059
线程31 退出 时间: 1621162350059
线程6 退出 时间: 1621162350059
线程3 退出 时间: 1621162350059
线程4 退出 时间: 1621162350059
线程16 退出 时间: 1621162350059
线程17 退出 时间: 1621162350059
线程29 退出 时间: 1621162350059
线程9 退出 时间: 1621162350059
线程157 进入 时间: 1621162350059
线程15 退出 时间: 1621162350059
线程33 退出 时间: 1621162350059
线程25 退出 时间: 1621162350059
线程21 退出 时间: 1621162350059
线程39 退出 时间: 1621162350059
线程18 退出 时间: 1621162350059
线程8 退出 时间: 1621162350059
线程127 进入 时间: 1621162350060
线程10 退出 时间: 1621162350059
线程131 进入 时间: 1621162350060
线程135 进入 时间: 1621162350060
线程139 进入 时间: 1621162350060
线程143 进入 时间: 1621162350060
线程145 进入 时间: 1621162350059
线程148 进入 时间: 1621162350059
线程162 进入 时间: 1621162350059
线程166 进入 时间: 1621162350059
线程168 进入 时间: 1621162350059
线程173 进入 时间: 1621162350059
线程180 进入 时间: 1621162350059
线程186 进入 时间: 1621162350059
线程190 进入 时间: 1621162350059
线程195 进入 时间: 1621162350059
线程197 进入 时间: 1621162350059
线程198 进入 时间: 1621162350059
线程199 进入 时间: 1621162350059
线程2 退出 时间: 1621162350059
线程7 退出 时间: 1621162350059
线程1 退出 时间: 1621162350059
线程23 退出 时间: 1621162350059
线程60 进入 时间: 1621162350062
线程51 进入 时间: 1621162350062
线程77 进入 时间: 1621162350062
线程121 进入 时间: 1621162350060
线程61 进入 时间: 1621162350062
线程143 退出 时间: 1621162350261
线程131 退出 时间: 1621162350261
线程139 退出 时间: 1621162350261
线程135 退出 时间: 1621162350261
线程127 退出 时间: 1621162350261
线程157 退出 时间: 1621162350261
线程178 进入 时间: 1621162350261
线程185 进入 时间: 1621162350261
线程191 进入 时间: 1621162350261
线程194 进入 时间: 1621162350261
线程196 进入 时间: 1621162350261
线程175 进入 时间: 1621162350261
线程61 退出 时间: 1621162350276
线程190 退出 时间: 1621162350276
线程121 退出 时间: 1621162350276
线程193 进入 时间: 1621162350276
线程77 退出 时间: 1621162350276
线程148 退出 时间: 1621162350276
线程166 退出 时间: 1621162350276
线程145 退出 时间: 1621162350276
线程51 退出 时间: 1621162350276
线程11 进入 时间: 1621162350276
线程52 进入 时间: 1621162350276
线程49 进入 时间: 1621162350276
线程179 进入 时间: 1621162350276
线程192 进入 时间: 1621162350276
线程189 进入 时间: 1621162350276
线程198 退出 时间: 1621162350276
线程199 退出 时间: 1621162350276
线程186 退出 时间: 1621162350276
线程173 退出 时间: 1621162350276
线程180 退出 时间: 1621162350276
线程197 退出 时间: 1621162350276
线程168 退出 时间: 1621162350276
线程60 退出 时间: 1621162350276
线程162 退出 时间: 1621162350276
线程195 退出 时间: 1621162350276
线程99 进入 时间: 1621162350277
线程95 进入 时间: 1621162350277
线程91 进入 时间: 1621162350277
线程90 进入 时间: 1621162350277
线程85 进入 时间: 1621162350277
线程80 进入 时间: 1621162350277
线程75 进入 时间: 1621162350277
线程71 进入 时间: 1621162350277
线程66 进入 时间: 1621162350276
线程30 进入 时间: 1621162350276
线程104 进入 时间: 1621162350277
线程178 退出 时间: 1621162350464
线程175 退出 时间: 1621162350464
线程194 退出 时间: 1621162350464
线程196 退出 时间: 1621162350464
线程191 退出 时间: 1621162350464
线程185 退出 时间: 1621162350464
线程48 进入 时间: 1621162350464
线程45 进入 时间: 1621162350465
线程176 进入 时间: 1621162350464
线程183 进入 时间: 1621162350464
线程187 进入 时间: 1621162350464
线程188 进入 时间: 1621162350464
线程30 退出 时间: 1621162350480
线程90 退出 时间: 1621162350480
线程95 退出 时间: 1621162350480
线程184 进入 时间: 1621162350480
线程52 退出 时间: 1621162350480
线程91 退出 时间: 1621162350480
线程49 退出 时间: 1621162350480
线程189 退出 时间: 1621162350480
线程193 退出 时间: 1621162350480
线程80 退出 时间: 1621162350480
线程124 进入 时间: 1621162350480
线程75 退出 时间: 1621162350480
线程99 退出 时间: 1621162350480
线程104 退出 时间: 1621162350480
线程85 退出 时间: 1621162350480
线程150 进入 时间: 1621162350480
线程140 进入 时间: 1621162350480
线程136 进入 时间: 1621162350480
线程126 进入 时间: 1621162350480
线程118 进入 时间: 1621162350480
线程114 进入 时间: 1621162350480
线程109 进入 时间: 1621162350480
线程28 进入 时间: 1621162350480
线程181 进入 时间: 1621162350480
线程182 进入 时间: 1621162350480
线程192 退出 时间: 1621162350480
线程11 退出 时间: 1621162350480
线程179 退出 时间: 1621162350480
线程66 退出 时间: 1621162350480
线程71 退出 时间: 1621162350480
线程42 进入 时间: 1621162350481
线程55 进入 时间: 1621162350481
线程54 进入 时间: 1621162350481
线程58 进入 时间: 1621162350481
线程153 进入 时间: 1621162350480
线程38 进入 时间: 1621162350481
线程45 退出 时间: 1621162350667
线程176 退出 时间: 1621162350667
线程48 退出 时间: 1621162350667
线程59 进入 时间: 1621162350667
线程177 进入 时间: 1621162350667
线程50 进入 时间: 1621162350667
线程183 退出 时间: 1621162350682
线程55 退出 时间: 1621162350682
线程109 退出 时间: 1621162350682
线程124 退出 时间: 1621162350682
线程184 退出 时间: 1621162350682
线程182 退出 时间: 1621162350682
线程181 退出 时间: 1621162350682
线程150 退出 时间: 1621162350682
线程54 退出 时间: 1621162350682
线程58 退出 时间: 1621162350682
线程153 退出 时间: 1621162350682
线程42 退出 时间: 1621162350682
线程28 退出 时间: 1621162350682
线程114 退出 时间: 1621162350682
线程188 退出 时间: 1621162350682
线程118 退出 时间: 1621162350682
线程187 退出 时间: 1621162350682
线程126 退出 时间: 1621162350682
线程152 进入 时间: 1621162350682
线程160 进入 时间: 1621162350682
线程164 进入 时间: 1621162350682
线程171 进入 时间: 1621162350682
线程102 进入 时间: 1621162350682
线程97 进入 时间: 1621162350682
线程92 进入 时间: 1621162350682
线程84 进入 时间: 1621162350682
线程78 进入 时间: 1621162350682
线程70 进入 时间: 1621162350682
线程63 进入 时间: 1621162350682
线程64 进入 时间: 1621162350682
线程19 进入 时间: 1621162350682
线程32 进入 时间: 1621162350682
线程14 进入 时间: 1621162350682
线程35 进入 时间: 1621162350682
线程56 进入 时间: 1621162350682
线程136 退出 时间: 1621162350682
线程140 退出 时间: 1621162350682
线程38 退出 时间: 1621162350682
线程86 进入 时间: 1621162350683
线程89 进入 时间: 1621162350683
线程146 进入 时间: 1621162350682
线程79 进入 时间: 1621162350683
线程177 退出 时间: 1621162350868
线程50 退出 时间: 1621162350868
线程59 退出 时间: 1621162350868
线程144 进入 时间: 1621162350868
线程141 进入 时间: 1621162350868
线程142 进入 时间: 1621162350868
线程56 退出 时间: 1621162350884
线程102 退出 时间: 1621162350884
线程152 退出 时间: 1621162350884
线程164 退出 时间: 1621162350884
线程97 退出 时间: 1621162350884
线程19 退出 时间: 1621162350884
线程92 退出 时间: 1621162350884
线程160 退出 时间: 1621162350884
线程84 退出 时间: 1621162350884
线程63 退出 时间: 1621162350884
线程35 退出 时间: 1621162350884
线程70 退出 时间: 1621162350884
线程171 退出 时间: 1621162350884
线程32 退出 时间: 1621162350884
线程78 退出 时间: 1621162350884
线程14 退出 时间: 1621162350884
线程64 退出 时间: 1621162350884
线程112 进入 时间: 1621162350885
线程108 进入 时间: 1621162350885
线程24 进入 时间: 1621162350885
线程149 进入 时间: 1621162350885
线程155 进入 时间: 1621162350884
线程159 进入 时间: 1621162350884
线程169 进入 时间: 1621162350884
线程103 进入 时间: 1621162350884
线程94 进入 时间: 1621162350884
线程87 进入 时间: 1621162350884
线程13 进入 时间: 1621162350884
线程40 进入 时间: 1621162350884
线程57 进入 时间: 1621162350884
线程67 进入 时间: 1621162350884
线程65 进入 时间: 1621162350884
线程74 进入 时间: 1621162350884
线程76 进入 时间: 1621162350884
线程89 退出 时间: 1621162350899
线程79 退出 时间: 1621162350899
线程146 退出 时间: 1621162350899
线程86 退出 时间: 1621162350899
线程43 进入 时间: 1621162350899
线程62 进入 时间: 1621162350899
线程73 进入 时间: 1621162350899
线程36 进入 时间: 1621162350899
线程144 退出 时间: 1621162351071
线程141 退出 时间: 1621162351071
线程72 进入 时间: 1621162351071
线程142 退出 时间: 1621162351071
线程53 进入 时间: 1621162351071
线程37 进入 时间: 1621162351071
线程57 退出 时间: 1621162351087
线程87 退出 时间: 1621162351087
线程169 退出 时间: 1621162351087
线程108 退出 时间: 1621162351087
线程13 退出 时间: 1621162351087
线程103 退出 时间: 1621162351087
线程67 退出 时间: 1621162351087
线程74 退出 时间: 1621162351087
线程149 退出 时间: 1621162351087
线程24 退出 时间: 1621162351087
线程76 退出 时间: 1621162351087
线程65 退出 时间: 1621162351087
线程155 退出 时间: 1621162351087
线程132 进入 时间: 1621162351087
线程138 进入 时间: 1621162351087
线程106 进入 时间: 1621162351087
线程147 进入 时间: 1621162351087
线程156 进入 时间: 1621162351087
线程165 进入 时间: 1621162351087
线程101 进入 时间: 1621162351087
线程93 进入 时间: 1621162351087
线程81 进入 时间: 1621162351087
线程44 进入 时间: 1621162351087
线程68 进入 时间: 1621162351087
线程69 进入 时间: 1621162351087
线程112 退出 时间: 1621162351087
线程94 退出 时间: 1621162351087
线程159 退出 时间: 1621162351087
线程40 退出 时间: 1621162351087
线程96 进入 时间: 1621162351088
线程172 进入 时间: 1621162351088
线程34 进入 时间: 1621162351088
线程27 进入 时间: 1621162351088
线程129 进入 时间: 1621162351087
线程36 退出 时间: 1621162351102
线程43 退出 时间: 1621162351102
线程62 退出 时间: 1621162351102
线程73 退出 时间: 1621162351102
线程88 进入 时间: 1621162351102
线程26 进入 时间: 1621162351102
线程41 进入 时间: 1621162351102
线程123 进入 时间: 1621162351102
线程53 退出 时间: 1621162351274
线程37 退出 时间: 1621162351274
线程72 退出 时间: 1621162351274
线程98 进入 时间: 1621162351274
线程12 进入 时间: 1621162351274
线程128 进入 时间: 1621162351274
线程27 退出 时间: 1621162351289
线程93 退出 时间: 1621162351289
线程138 退出 时间: 1621162351289
线程101 退出 时间: 1621162351289
线程165 退出 时间: 1621162351289
线程147 退出 时间: 1621162351289
线程96 退出 时间: 1621162351289
线程132 退出 时间: 1621162351289
线程68 退出 时间: 1621162351289
线程44 退出 时间: 1621162351289
线程34 退出 时间: 1621162351289
线程134 进入 时间: 1621162351289
线程133 进入 时间: 1621162351289
线程156 退出 时间: 1621162351289
线程110 进入 时间: 1621162351289
线程129 退出 时间: 1621162351289
线程107 进入 时间: 1621162351289
线程158 进入 时间: 1621162351289
线程161 进入 时间: 1621162351289
线程47 进入 时间: 1621162351289
线程137 进入 时间: 1621162351289
线程113 进入 时间: 1621162351289
线程119 进入 时间: 1621162351289
线程83 进入 时间: 1621162351289
线程82 进入 时间: 1621162351289
线程106 退出 时间: 1621162351289
线程81 退出 时间: 1621162351289
线程69 退出 时间: 1621162351289
线程172 退出 时间: 1621162351289
线程105 进入 时间: 1621162351291
线程122 进入 时间: 1621162351291
线程130 进入 时间: 1621162351290
线程154 进入 时间: 1621162351290
线程163 进入 时间: 1621162351291
线程123 退出 时间: 1621162351304
线程115 进入 时间: 1621162351304
线程41 退出 时间: 1621162351304
线程26 退出 时间: 1621162351304
线程88 退出 时间: 1621162351304
线程100 进入 时间: 1621162351304
线程170 进入 时间: 1621162351304
线程111 进入 时间: 1621162351304
线程12 退出 时间: 1621162351475
线程128 退出 时间: 1621162351475
线程98 退出 时间: 1621162351475
线程117 进入 时间: 1621162351475
线程174 进入 时间: 1621162351475
线程151 进入 时间: 1621162351475
线程134 退出 时间: 1621162351490
线程133 退出 时间: 1621162351490
线程120 进入 时间: 1621162351490
线程46 进入 时间: 1621162351490
线程154 退出 时间: 1621162351505
线程113 退出 时间: 1621162351505
线程116 进入 时间: 1621162351505
线程100 退出 时间: 1621162351505
线程167 进入 时间: 1621162351505
线程107 退出 时间: 1621162351505
线程161 退出 时间: 1621162351505
线程47 退出 时间: 1621162351505
线程115 退出 时间: 1621162351505
线程111 退出 时间: 1621162351505
线程170 退出 时间: 1621162351505
线程137 退出 时间: 1621162351505
线程83 退出 时间: 1621162351505
线程82 退出 时间: 1621162351505
线程110 退出 时间: 1621162351505
线程119 退出 时间: 1621162351505
线程158 退出 时间: 1621162351505
线程122 退出 时间: 1621162351505
线程130 退出 时间: 1621162351505
线程163 退出 时间: 1621162351505
线程105 退出 时间: 1621162351505
线程125 进入 时间: 1621162351505
线程117 退出 时间: 1621162351678
线程151 退出 时间: 1621162351678
线程174 退出 时间: 1621162351678
线程46 退出 时间: 1621162351694
线程120 退出 时间: 1621162351694
线程125 退出 时间: 1621162351709
线程116 退出 时间: 1621162351709
线程167 退出 时间: 1621162351709
Process finished with exit code 0
通过测试,MySemaphore基本实现了线程同步和限流作用,测试结果与Semaphore一致。
以上是关于用synchronized实现Semaphore的主要内容,如果未能解决你的问题,请参考以下文章
Semaphore替换多线程synchronized解决并发环境死锁,Java