Java信号量(Semaphore)是一种用于控制多线程并发访问的同步工具类,它的原理是基于计数器的,可以用来限制同时访问特定资源的线程数量,信号量的值表示当前可用的资源数,当资源数为0时,线程需要等待;当资源数大于0时,线程可以继续执行。
在Java中,信号量可以通过java.util.concurrent.Semaphore类来实现,Semaphore类提供了一些方法来操作信号量,如acquire()、release()和tryAcquire()等,下面我们将详细介绍如何使用Java信号量。
1、创建信号量对象
我们需要创建一个Semaphore对象,并指定初始的资源数,我们创建一个初始资源数为3的信号量对象:
import java.util.concurrent.Semaphore; public class SemaphoreDemo { public static void main(String[] args) { Semaphore semaphore = new Semaphore(3); // 创建一个初始资源数为3的信号量对象 } }
2、获取资源
当一个线程需要访问某个资源时,它需要先调用acquire()方法来获取资源,如果信号量的值为正数,表示有可用的资源,线程将继续执行;如果信号量的值为0,表示没有可用的资源,线程需要等待。
import java.util.concurrent.Semaphore; public class SemaphoreDemo { public static void main(String[] args) { Semaphore semaphore = new Semaphore(3); // 创建一个初始资源数为3的信号量对象 // 线程1尝试获取资源 new Thread(() > { try { semaphore.acquire(); // 获取资源 System.out.println("线程1获取到资源"); } catch (InterruptedException e) { e.printStackTrace(); } finally { semaphore.release(); // 释放资源 } }).start(); } }
3、释放资源
当一个线程不再需要访问某个资源时,它需要调用release()方法来释放资源,这将使信号量的值加1,允许其他等待的线程继续执行,注意,释放资源的操作必须在finally代码块中进行,以确保即使在异常情况下也能正确释放资源。
import java.util.concurrent.Semaphore; public class SemaphoreDemo { public static void main(String[] args) { Semaphore semaphore = new Semaphore(3); // 创建一个初始资源数为3的信号量对象 // 线程1尝试获取资源 new Thread(() > { try { semaphore.acquire(); // 获取资源 System.out.println("线程1获取到资源"); } catch (InterruptedException e) { e.printStackTrace(); } finally { semaphore.release(); // 释放资源 } }).start(); } }
4、尝试获取资源(非阻塞)
除了使用acquire()方法阻塞等待资源外,我们还可以使用tryAcquire()方法尝试获取资源,如果信号量的值为正数,表示有可用的资源,线程将继续执行;如果信号量的值为0,表示没有可用的资源,线程不会等待,而是直接返回false,这样可以避免线程长时间等待资源的情况。
import java.util.concurrent.Semaphore; import java.util.concurrent.TimeUnit; public class SemaphoreDemo { public static void main(String[] args) { Semaphore semaphore = new Semaphore(3); // 创建一个初始资源数为3的信号量对象 // 线程1尝试获取资源(非阻塞) boolean result = semaphore.tryAcquire(); // 尝试获取资源,非阻塞方式 if (result) { // 如果成功获取到资源,继续执行 System.out.println("线程1获取到资源"); } else { // 如果未能获取到资源,执行其他操作或等待一段时间后重试 System.out.println("线程1未能获取到资源"); } finally { semaphore.release(); // 释放资源(无论是否成功获取到资源) } } }
5、超时等待资源(限时获取)
我们希望线程在等待资源的限定时间内能够获取到资源,这时,我们可以使用tryAcquire()方法结合时间参数来实现,我们让线程在1秒内尝试获取资源:
import java.util.concurrent.Semaphore; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.locks.Condition; import java.util.concurrent.locks.ReentrantLock; import java.util.function.Supplier; import java.util.stream.IntStream; import java.util.stream.Stream; import org.junit.Test; import static org.junit.Assert.*; import static org.mockito.Mockito.*; import static org.mockito.MockitoAnnotations.*; import java.util.*;; import javafx.*; import javafx.application.*; import javafx.scene.*; import javafx.scene,layout.*; import javafx,stage.*; import javafx,embed.*; import javafx,scene,control.*; import javafx,scene,input.*; import javafx,scene,paint.*; import javafx,scene,shape.*; import javafx,scene,text.*; import javafx,stage,filedialog.*; import javafx,stage,modaldialog.*; import javafx,stage,alert.*; import javafx,stage,tab.*; import javafx,stage,title.*; import javafx,scene,image.*; import javafx,scene,web.*; import javax,xml,bind.*; import javax,xml,parsers.*; import javax,xml,transform.*; import javax,xml,transform,dom.*; import javax,xml,transform,stream.*; import javax,xml,xpath.*; import org,w3c,dom.*; import org,w3c,dom,events.*; import org,w3c,dom,ls.*; import org,w3c,dom,ranges.*; import org,w3c,dom,stylesheets.*; import org,w3c,dom,traversal.*; import org,w3c,dom,views.*; import org,xml,sax.*; import org,xml,sax,helpers.*; import org,xmlpull.*; import com,sun,org,apache,xerces.*; import com
原创文章,作者:酷盾叔,如若转载,请注明出处:https://www.kdun.com/ask/294401.html
本网站发布或转载的文章及图片均来自网络,其原创性以及文中表达的观点和判断不代表本网站。如有问题,请联系客服处理。
发表回复