Synchronized
实例:三个售票员销售三十张票
package com.yyp.demo02;
//创建资源类
class Ticket{
private int number = 300;
public synchronized void sale(){
if (number>0){
System.out.println(Thread.currentThread().getName()+":卖出了:"
+(number--)+":剩余:"+number);
}
}
}
public class SaleTicket {
//第二步创建多个线程,调用资源类操作方法
public static void main(String[] args) {
Ticket ticket = new Ticket();
new Thread(new Runnable() {
@Override
public void run() {
for (int i = 0;i<400;i++){
ticket.sale();
}
}
},"AA").start();
new Thread(new Runnable() {
@Override
public void run() {
for (int i = 0;i<400;i++){
ticket.sale();
}
}
},"BB").start();
new Thread(new Runnable() {
@Override
public void run() {
for (int i = 0;i<400;i++){
ticket.sale();
}
}
},"CC").start();
}
}
Lock接口
可重入锁
还是卖票的的实例:
package com.yyp.demo02;
import java.util.concurrent.locks.ReentrantLock;
class LTicket{
private int number=3000;
//创建可重入锁
private final ReentrantLock lock=new ReentrantLock();
public void sale(){
lock.lock();
try {
if (number>0){
System.out.println(Thread.currentThread().getName()+":卖出了:"
+(number--)+":剩余:"+number);
}
} finally {
lock.unlock();
}
}
}
public class LSaleTicket {
public static void main(String[] args) {
LTicket ticket = new LTicket();
new Thread(new Runnable() {
@Override
public void run() {
for (int i = 0;i<1000;i++){
ticket.sale();
}
}
},"AA").start();
new Thread(new Runnable() {
@Override
public void run() {
for (int i = 0;i<1000;i++){
ticket.sale();
}
}
},"BB").start();
new Thread(new Runnable() {
@Override
public void run() {
for (int i = 0;i<1000;i++){
ticket.sale();
}
}
},"CC").start();
}
}
Synchronized和Lock的区别
- Lock是一个接口,而synchronized是Java中的关键字,synchronized是内
置的语言实现; - synchronized在发生异常时,会自动释放线程占有的锁,因此不会导致死锁现
象发生;而Lock在发生异常时,如果没有主动通过unLock()去释放锁,则很可能造成死锁现象,因此使用Lock时需要在finally块中释放锁;· - Lock可以让等待锁的线程响应中断,而synchronized却不行,使用synchronized时,等待的线程会一直等待下去,不能够响应中断;
- 通过Lock可以知道有没有成功获取锁,而synchronized却无法办到。
- Lock可以提高多个线程进行读操作的效率。
带通知的实例
有两个线程,实现对一个初始值是0的变量进行操作,一个线程+1,一个线程-1
Synchronized实现
package com.yyp.demo03;
class Share{
private int number=0;
public synchronized void incr() throws InterruptedException {
if (number!=0){
this.wait();
}
number++;
System.out.println(Thread.currentThread().getName()+"::"+number);
this.notifyAll();
}
public synchronized void decr() throws InterruptedException {
if (number!=1){
this.wait();
}
number--;
System.out.println(Thread.currentThread().getName()+"::"+number);
this.notifyAll();
}
}
public class TreadDemo1 {
public static void main(String[] args) {
Share share = new Share();
new Thread(()->{
for (int i= 1;i<=10;i++){
try {
share.incr();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
},"A").start();
new Thread(()->{
for (int i= 1;i<=10;i++){
try {
share.decr();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
},"B").start();
}
}
可能会有虚假唤醒的情况,我们要防止虚假唤醒的情况。
Lock实现
package com.yyp.demo03;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
class LShare{
private int number=0;
private Lock lock=new ReentrantLock();
private Condition condition = lock.newCondition();
public void incr() throws InterruptedException {
lock.lock();
try {
while (number!=0){
condition.await();
}
number++;
System.out.println(Thread.currentThread().getName()+"::"+number);
condition.signalAll();
}finally {
lock.unlock();
}
}
public void decr() throws InterruptedException {
lock.lock();
try {
while (number!=1){
condition.await();
}
number--;
System.out.println(Thread.currentThread().getName()+"::"+number);
condition.signalAll();
}finally {
lock.unlock();
}
}
}
public class Treaddemo2 {
public static void main(String[] args) {
LShare share = new LShare();
new Thread(()->{
for (int i= 1;i<=10;i++){
try {
share.incr();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
},"A").start();
new Thread(()->{
for (int i= 1;i<=10;i++){
try {
share.decr();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
},"B").start();
}
}
线程间定制化通信
要求,启动三个线程,
AA打印五次,BB打印十次,CC打印十五次,执行10轮
package com.yyp.demo04;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
class ShareResource{
private int flag = 1;
private Lock lock = new ReentrantLock();
private Condition c1 = lock.newCondition();
private Condition c2 = lock.newCondition();
private Condition c3 = lock.newCondition();
public void print5(int loop) throws InterruptedException {
lock.lock();
try{
while (flag !=1){
c1.await();
}
for (int i=1;i<=5;i++){
System.out.println(Thread.currentThread().getName()+"::"+i+":轮数:"+loop);
flag = 2;
c2.signal();
}
}finally {
lock.unlock();
}
}
public void print10(int loop) throws InterruptedException {
lock.lock();
try{
while (flag !=2){
c1.await();
}
for (int i=1;i<=10;i++){
System.out.println(Thread.currentThread().getName()+"::"+i+":轮数:"+loop);
flag = 3;
c3.signal();
}
}finally {
lock.unlock();
}
}
public void print15(int loop) throws InterruptedException {
lock.lock();
try{
while (flag !=3){
c3.await();
}
for (int i=1;i<=15;i++){
System.out.println(Thread.currentThread().getName()+"::"+i+":轮数:"+loop);
flag = 1;
c1.signal();
}
}finally {
lock.unlock();
}
}
}
public class ThreadDemo03 {
public static void main(String[] args) {
ShareResource shareResource = new ShareResource();
new Thread(()->{
for (int i=0;i<10;i++){
try {
shareResource.print5(i+1);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
},"AA").start();
new Thread(()->{
for (int i=0;i<10;i++){
try {
shareResource.print10(i+1);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
},"BB").start();
new Thread(()->{
for (int i=0;i<10;i++){
try {
shareResource.print15(i+1);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
},"CC").start();
}
}