Java并发编程实例--18.修改锁的公平性
ReentrantLock和ReentrantReadWriteLock类的构造函数可接受一个布尔类型参数fair,表示你可以控制这2个类的行为。
其默认值为false,代表non-fair(不公平)模式。
这种模式下,如果有多个线程等待获得锁并且只能有一个线程获得,上面2个锁类会无条件选择一个。(也就是随机抽一个)
值为true的话就表示fair模式,即公平模式。
意思是有个先来后到,就跟咱们买东西要排队一样。锁会分给那个等了最长时间的线程。
以上逻辑仅适用于lock() and unlock()方法。因为例如tryLock()方法压根不会让线程睡眠。
本例中,我们将修改一下之前使用锁机制同步代码块的程序,加入这个参数来对比一下fair和non-fair两种模式的差别。
PrintQueue.java
package com.dylan.thread.ch2.c06.task;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
/**
* This class simulates a print queue.
*
*/
public class PrintQueue {
/**
* Creates a lock to control the access to the queue.
* With the boolean attribute, we control the fairness of
* the Lock
*/
private final Lock queueLock=new ReentrantLock(false);
/**
* Method that prints the Job. The printing is divided in two phase two
* show how the fairness attribute affects the election of the thread who
* has the control of the lock
* @param document The document to print
*/
public void printJob(Object document){
queueLock.lock();
try {
Long duration=(long)(Math.random()*10000);
System.out.printf("%s: PrintQueue: Printing a Job during %d seconds\n",Thread.currentThread().getName(),(duration/1000));
Thread.sleep(duration);
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
queueLock.unlock();
}
queueLock.lock();
try {
Long duration=(long)(Math.random()*10000);
System.out.printf("%s: PrintQueue: Printing a Job during %d seconds\n",Thread.currentThread().getName(),(duration/1000));
Thread.sleep(duration);
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
queueLock.unlock();
}
}
}
Job.java
package com.dylan.thread.ch2.c06.task;
/**
* This class simulates a job that send a document to print
*
*/
public class Job implements Runnable {
/**
* The queue to send the documents
*/
private PrintQueue printQueue;
/**
* Constructor of the class. Initializes the print queue
* @param printQueue the print queue to send the documents
*/
public Job(PrintQueue printQueue){
this.printQueue=printQueue;
}
/**
* Core method of the Job. Sends the document to the queue
*/
@Override
public void run() {
System.out.printf("%s: Going to print a job\n",Thread.currentThread().getName());
printQueue.printJob(new Object());
System.out.printf("%s: The document has been printed\n",Thread.currentThread().getName());
}
}
Main.java
package com.dylan.thread.ch2.c06.core;
import com.dylan.thread.ch2.c06.task.Job;
import com.dylan.thread.ch2.c06.task.PrintQueue;
/**
* Main class of the example
*
*/
public class Main {
/**
* Main method of the example
* @param args
*/
public static void main (String args[]){
// Creates the print queue
PrintQueue printQueue=new PrintQueue();
// Cretes ten jobs and the Threads to run them
Thread thread[]=new Thread[10];
for (int i=0; i<10; i++){
thread[i]=new Thread(new Job(printQueue),"Thread "+i);
}
// Launch a thread ever 0.1 seconds
for (int i=0; i<10; i++){
thread[i].start();
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
运行结果:
1.不公平模式:
Thread 0: Going to print a job
Thread 0: PrintQueue: Printing a Job during 0 seconds
Thread 1: Going to print a job
Thread 2: Going to print a job
Thread 3: Going to print a job
Thread 4: Going to print a job
Thread 5: Going to print a job
Thread 6: Going to print a job
Thread 0: PrintQueue: Printing a Job during 1 seconds
Thread 7: Going to print a job
Thread 8: Going to print a job
Thread 9: Going to print a job
Thread 1: PrintQueue: Printing a Job during 1 seconds
Thread 0: The document has been printed
Thread 1: PrintQueue: Printing a Job during 8 seconds
Thread 1: The document has been printed
Thread 2: PrintQueue: Printing a Job during 3 seconds
Thread 2: PrintQueue: Printing a Job during 8 seconds
Thread 2: The document has been printed
Thread 3: PrintQueue: Printing a Job during 6 seconds
Thread 3: PrintQueue: Printing a Job during 5 seconds
Thread 3: The document has been printed
Thread 4: PrintQueue: Printing a Job during 9 seconds
Thread 5: PrintQueue: Printing a Job during 3 seconds
Thread 5: PrintQueue: Printing a Job during 1 seconds
Thread 6: PrintQueue: Printing a Job during 1 seconds
Thread 5: The document has been printed
Thread 6: PrintQueue: Printing a Job during 6 seconds
Thread 6: The document has been printed
Thread 7: PrintQueue: Printing a Job during 8 seconds
Thread 7: PrintQueue: Printing a Job during 5 seconds
Thread 7: The document has been printed
Thread 8: PrintQueue: Printing a Job during 7 seconds
Thread 8: PrintQueue: Printing a Job during 5 seconds
Thread 8: The document has been printed
Thread 9: PrintQueue: Printing a Job during 1 seconds
Thread 9: PrintQueue: Printing a Job during 3 seconds
Thread 9: The document has been printed
Thread 4: PrintQueue: Printing a Job during 7 seconds
Thread 4: The document has been printed
2.公平模式:
Thread 0: Going to print a job
Thread 0: PrintQueue: Printing a Job during 1 seconds
Thread 1: Going to print a job
Thread 2: Going to print a job
Thread 3: Going to print a job
Thread 4: Going to print a job
Thread 5: Going to print a job
Thread 6: Going to print a job
Thread 7: Going to print a job
Thread 8: Going to print a job
Thread 9: Going to print a job
Thread 1: PrintQueue: Printing a Job during 8 seconds
Thread 2: PrintQueue: Printing a Job during 9 seconds
Thread 3: PrintQueue: Printing a Job during 0 seconds
Thread 4: PrintQueue: Printing a Job during 3 seconds
Thread 5: PrintQueue: Printing a Job during 1 seconds
Thread 6: PrintQueue: Printing a Job during 0 seconds
Thread 7: PrintQueue: Printing a Job during 7 seconds
Thread 8: PrintQueue: Printing a Job during 3 seconds
Thread 9: PrintQueue: Printing a Job during 4 seconds
Thread 0: PrintQueue: Printing a Job during 6 seconds
Thread 0: The document has been printed
Thread 1: PrintQueue: Printing a Job during 9 seconds
Thread 1: The document has been printed
Thread 2: PrintQueue: Printing a Job during 4 seconds
Thread 2: The document has been printed
Thread 3: PrintQueue: Printing a Job during 3 seconds
Thread 3: The document has been printed
Thread 4: PrintQueue: Printing a Job during 1 seconds
Thread 5: PrintQueue: Printing a Job during 3 seconds
Thread 4: The document has been printed
Thread 5: The document has been printed
Thread 6: PrintQueue: Printing a Job during 0 seconds
Thread 6: The document has been printed
Thread 7: PrintQueue: Printing a Job during 0 seconds
Thread 7: The document has been printed
Thread 8: PrintQueue: Printing a Job during 3 seconds
Thread 9: PrintQueue: Printing a Job during 1 seconds
Thread 8: The document has been printed
Thread 9: The document has been printed
Java并发编程实例--18.修改锁的公平性的更多相关文章
- Java并发编程实战 03互斥锁 解决原子性问题
文章系列 Java并发编程实战 01并发编程的Bug源头 Java并发编程实战 02Java如何解决可见性和有序性问题 摘要 在上一篇文章02Java如何解决可见性和有序性问题当中,我们解决了可见性和 ...
- Java并发编程:线程和锁的使用与解析
线程的使用 新建线程 新建一个线程有两种方法:继承Thread类,然后重写run方法:实现Runnable接口,然后实现run方法.实际上Thread类也是实现的Runnable接口,再加上类只能单 ...
- Java并发编程(05):悲观锁和乐观锁机制
本文源码:GitHub·点这里 || GitEE·点这里 一.资源和加锁 1.场景描述 多线程并发访问同一个资源问题,假如线程A获取变量之后修改变量值,线程C在此时也获取变量值并且修改,两个线程同时并 ...
- Java并发编程:Lock(锁)
一.synchronized的缺陷 synchronized是java中的一个关键字,也就是说是Java语言内置的特性.那么为什么会出现Lock呢? 在上面一篇文章中,我们了解到如果一个代码块被syn ...
- Java并发编程笔记之StampedLock锁源码探究
StampedLock是JUC并发包里面JDK1.8版本新增的一个锁,该锁提供了三种模式的读写控制,当调用获取锁的系列函数的时候,会返回一个long 型的变量,该变量被称为戳记(stamp),这个戳记 ...
- Java并发编程-可重入锁
可重入锁,也叫做递归锁,指的是同一线程 外层函数获得锁之后 ,内层递归函数仍可以获取该锁而不受影响.在JAVA环境下 ReentrantLock 和synchronized 都是 可重入锁. publ ...
- Java并发编程实例(synchronized)
此处用一个小程序来说明一下,逻辑是一个计数器(int i):主要的逻辑功能是,如果同步监视了资源i,则不输出i的值,但如果没有添加关键字synchronized,因为是两个线程并发执行,所以会输出i的 ...
- Java并发编程(五)锁的使用(下)
显式锁 上篇讲了使用synchronized关键字来定义锁,其实Java除了使用这个关键字外还可以使用Lock接口及其实现的子类来定义锁,ReentrantLock类是Lock接口的一个实现,Reen ...
- Java并发编程:synchronized和锁优化
1. 使用方法 synchronized 是 java 中最常用的保证线程安全的方式,synchronized 的作用主要有三方面: 确保线程互斥的访问代码块,同一时刻只有一个方法可以进入到临界区 保 ...
- Java并发编程之显式锁机制
我们之前介绍过synchronized关键字实现程序的原子性操作,它的内部也是一种加锁和解锁机制,是一种声明式的编程方式,我们只需要对方法或者代码块进行声明,Java内部帮我们在调用方法之前和结束时加 ...
随机推荐
- vCenter6.7 无法启动
Get service 567f6edd-d4f7-4bfb-905b-1834c758a99d_com.vmware.vsphere.clientDon't update service 567f6 ...
- [转帖]36.堆空间的参数设置和-XX:HandlePromotionFailure
目录 1.堆空间参数 2.-XX:HandlePromotionFailure 1.堆空间参数 * -XX:+PrintFlagsInitial : 查看所有的参数的默认初始值 * -XX:+Prin ...
- CPU实际频率查看
cat /sys/devices/system/cpu/cpu3/cpufreq/cpuinfo_cur_freq
- SQL注入payload学习整理
SQLserver 用的payload 0101%'and 1=(select @@version) and '%'=' GS的一个客户端参数 <add PropertyName="F ...
- 容器方式运行Mysql8.0.26的方法
容器化运行Mysql8.0.26测试环境的方法 1. 前言 之前为了好处理,都是二进制包的方式安装mysql,但是有时候需要下载和安装也比较费时费力, 今天中午在弄Oracle RAC时想着以后能够容 ...
- js中的宏任务和微任务详细讲解
微任务有哪些 Promise await和async 宏任务有哪些 setTimeout setInterval DOM事件 AJAX请求 看下面的代码 <script> console. ...
- [LeetCode刷题记录]113 路径总和 II
题目描述 给定一个二叉树和一个目标和,找到所有从根节点到叶子节点路径总和等于给定目标和的路径. 说明: 叶子节点是指没有子节点的节点. 难度 中等 题解 采用深度搜索优先,遍历每条从根节点到叶子节点的 ...
- py 学习(c++ to py)
py1: print 2024-01-27 23:18:57 星期六 #这里是注释 # py1 : 基础print总结 ''' aaa 有时候也用三个单引号当注释 但其实是字符串 交互式会输出 ''' ...
- Proteus仿真出现“Internal Exception: access violation in module ‘LOADERS.DLL‘ [00020627].”错误
Proteus仿真问题 在使用 Proteus 8.4 进行仿真时, 出现错误提示 Internal Exception: access violation in module 'LOADERS.DL ...
- 高精度模板 大数乘以小数 vector实现
vector<int> Mul(vector<int>& A, int &B) { vector<int>C; int T = 0; for (in ...