第一部分:线程不安全的三大案例:
1.集合列表案例:
public class UnsafeList {
public static void main ( String [ ] args) {
List < String > list = new ArrayList < > ( ) ;
for ( int i = 0 ; i < 10000 ; i++ ) {
new Thread ( ( ) -> {
synchronized ( list) {
list. add ( Thread . currentThread ( ) . getName ( ) ) ;
}
} ) . start ( ) ;
}
System . out. println ( list. size ( ) ) ;
}
}
2.购票案例(会出现负的票数):
public class UnsafeBuyTicket {
public static void main ( String [ ] args) {
BuyTicket buyTicket = new BuyTicket ( ) ;
new Thread ( buyTicket, "苦逼的我" ) . start ( ) ;
new Thread ( buyTicket, "牛逼的你们" ) . start ( ) ;
new Thread ( buyTicket, "黄牛党" ) . start ( ) ;
}
}
class BuyTicket implements Runnable {
private int ticketNums = 10 ;
boolean flag = true ;
@Override
public void run ( ) {
while ( flag) {
try {
buy ( ) ;
} catch ( InterruptedException e) {
e. printStackTrace ( ) ;
}
}
}
private void buy ( ) throws InterruptedException {
if ( ticketNums <= 0 ) {
flag = false ;
return ;
}
Thread . sleep ( 50 ) ;
System . out. println ( Thread . currentThread ( ) . getName ( ) + "拿到了" + ticketNums-- ) ;
}
}
解决方法:(buy方法中加一个synchronized 同步方法)
public class UnsafeBuyTicket {
public static void main ( String [ ] args) {
BuyTicket buyTicket = new BuyTicket ( ) ;
new Thread ( buyTicket, "苦逼的我" ) . start ( ) ;
new Thread ( buyTicket, "牛逼的你们" ) . start ( ) ;
new Thread ( buyTicket, "黄牛党" ) . start ( ) ;
}
}
class BuyTicket implements Runnable {
private int ticketNums = 10 ;
boolean flag = true ;
@Override
public void run ( ) {
while ( flag) {
try {
buy ( ) ;
} catch ( InterruptedException e) {
e. printStackTrace ( ) ;
}
}
}
private synchronized void buy ( ) throws InterruptedException {
if ( ticketNums <= 0 ) {
flag = false ;
return ;
}
Thread . sleep ( 50 ) ;
System . out. println ( Thread . currentThread ( ) . getName ( ) + "拿到了" + ticketNums-- ) ;
}
}
3.银行取钱案例:
public class UnsafeBank {
public static void main ( String [ ] args) {
Account account = new Account ( 100 , "结婚基金" ) ;
Drawing you = new Drawing ( account, 50 , "你" ) ;
Drawing girlFriend = new Drawing ( account, 100 , "girlFriend" ) ;
you. start ( ) ;
girlFriend. start ( ) ;
}
}
class Account {
int money;
String name;
public Account ( int money, String name) {
this . money = money;
this . name = name;
}
}
class Drawing extends Thread {
Account account;
int drawingMoney;
int nowMoney;
public Drawing ( Account account, int drawingMoney, String name) {
super ( name) ;
this . account = account;
this . drawingMoney = drawingMoney;
}
@Override
public void run ( ) {
super . run ( ) ;
if ( account. money- drawingMoney < 0 ) {
System . out. println ( Thread . currentThread ( ) . getName ( ) + "钱不够了, 取不了" ) ;
return ;
}
try {
Thread . sleep ( 1000 ) ;
} catch ( InterruptedException e) {
e. printStackTrace ( ) ;
}
account. money = account. money- drawingMoney;
nowMoney = nowMoney + drawingMoney;
System . out. println ( account. name + "余额为" + account. money) ;
System . out. println ( this . getName ( ) + "手里的钱" + nowMoney) ;
}
}
解决方法:(加一个同步块)
public class UnsafeBank {
public static void main ( String [ ] args) {
Account account = new Account ( 100 , "结婚基金" ) ;
Drawing you = new Drawing ( account, 50 , "你" ) ;
Drawing girlFriend = new Drawing ( account, 100 , "girlFriend" ) ;
you. start ( ) ;
girlFriend. start ( ) ;
}
}
class Account {
int money;
String name;
public Account ( int money, String name) {
this . money = money;
this . name = name;
}
}
class Drawing extends Thread {
Account account;
int drawingMoney;
int nowMoney;
public Drawing ( Account account, int drawingMoney, String name) {
super ( name) ;
this . account = account;
this . drawingMoney = drawingMoney;
}
@Override
public void run ( ) {
super . run ( ) ;
synchronized ( account) {
if ( account. money- drawingMoney < 0 ) {
System . out. println ( Thread . currentThread ( ) . getName ( ) + "钱不够了, 取不了" ) ;
return ;
}
try {
Thread . sleep ( 1000 ) ;
} catch ( InterruptedException e) {
e. printStackTrace ( ) ;
}
account. money = account. money- drawingMoney;
nowMoney = nowMoney + drawingMoney;
System . out. println ( account. name + "余额为" + account. money) ;
System . out. println ( this . getName ( ) + "手里的钱" + nowMoney) ;
}
}
}
第二部分: 线程死锁问题:
public class DeadLock {
public static void main ( String [ ] args) {
Makeup g1 = new Makeup ( 0 , "灰姑娘" ) ;
Makeup g2 = new Makeup ( 1 , "白雪公主" ) ;
g1. start ( ) ;
g2. start ( ) ;
}
}
class Lipstick {
}
class Mirror {
}
class Makeup extends Thread {
static Lipstick lipstick = new Lipstick ( ) ;
static Mirror mirror = new Mirror ( ) ;
int choice;
String girlName;
public Makeup ( int choice, String girlName) {
this . choice = choice;
this . girlName = girlName;
}
@Override
public void run ( ) {
super . run ( ) ;
try {
makeup ( ) ;
} catch ( InterruptedException e) {
e. printStackTrace ( ) ;
}
}
private void makeup ( ) throws InterruptedException {
if ( choice== 0 ) {
synchronized ( lipstick) {
System . out. println ( lipstick) ;
System . out. println ( this . girlName+ "获得口红的锁" ) ;
Thread . sleep ( 1000 ) ;
synchronized ( mirror) {
System . out. println ( this . girlName+ "获得镜子的锁" ) ;
}
}
} else {
synchronized ( mirror) {
System . out. println ( lipstick) ;
System . out. println ( this . girlName+ "获得口红的锁" ) ;
synchronized ( lipstick) {
System . out. println ( this . girlName+ "获得的镜子锁" ) ;
Thread . sleep ( 1000 ) ;
}
}
}
}
}
解决方法(不要锁中套锁)
lock锁的应用
public class TestLock {
public static void main ( String [ ] args) {
TestLock2 testLock2 = new TestLock2 ( ) ;
new Thread ( testLock2) . start ( ) ;
new Thread ( testLock2) . start ( ) ;
new Thread ( testLock2) . start ( ) ;
}
}
class TestLock2 implements Runnable {
private final ReentrantLock lock = new ReentrantLock ( ) ;
int ticketNums = 10 ;
@Override
public void run ( ) {
while ( true ) {
try {
lock. lock ( ) ;
if ( ticketNums > 0 ) {
try {
Thread . sleep ( 1000 ) ;
} catch ( InterruptedException e) {
e. printStackTrace ( ) ;
}
System . out. println ( Thread . currentThread ( ) . getName ( ) + ":\t" + ticketNums-- ) ;
} else {
break ;
}
} finally {
lock. unlock ( ) ;
}
}
}
}
第三部分:线程同步方法
1.生产者消费者模式
public class TestPC {
public static void main ( String [ ] args) {
SynContainer container = new SynContainer ( ) ;
Productor productor = new Productor ( container) ;
Consumer consumer = new Consumer ( container) ;
productor. start ( ) ;
consumer. start ( ) ;
}
}
class Productor extends Thread {
SynContainer container;
public Productor ( SynContainer container) {
this . container = container;
}
@Override
public void run ( ) {
super . run ( ) ;
for ( int i = 0 ; i < 100 ; i++ ) {
container. push ( new Chicken ( i) ) ;
System . out. println ( "生产了" + i+ "只鸡" ) ;
}
}
}
class Consumer extends Thread {
SynContainer container;
public Consumer ( SynContainer container) {
this . container = container;
}
@Override
public void run ( ) {
super . run ( ) ;
for ( int i = 0 ; i < 100 ; i++ ) {
container. pop ( ) ;
System . out. println ( "消费了第" + i+ "只鸡" ) ;
}
}
}
class Chicken {
int id;
public Chicken ( int id) {
this . id = id;
}
}
class SynContainer {
Chicken [ ] chickens = new Chicken [ 10 ] ;
int count;
public synchronized void push ( Chicken chicken) {
if ( count== chickens. length) {
try {
this . wait ( ) ;
} catch ( InterruptedException e) {
e. printStackTrace ( ) ;
}
}
chickens[ count] = chicken;
count++ ;
this . notifyAll ( ) ;
}
public synchronized Chicken pop ( ) {
if ( count == 0 ) {
try {
this . wait ( ) ;
} catch ( InterruptedException e) {
e. printStackTrace ( ) ;
}
}
count-- ;
Chicken chicken = chickens[ count] ;
this . notifyAll ( ) ;
return chicken;
}
}
2.信号灯法
public class TestPC2 {
public static void main ( String [ ] args) {
Tv tv = new Tv ( ) ;
new Player ( tv) . start ( ) ;
new Watcher ( tv) . start ( ) ;
}
}
class Player extends Thread {
Tv tv;
public Player ( Tv tv) {
this . tv = tv;
}
@Override
public void run ( ) {
super . run ( ) ;
for ( int i = 0 ; i < 20 ; i++ ) {
if ( i% 2 == 0 ) {
this . tv. play ( "快乐大本营播放" ) ;
} else {
this . tv. play ( "记录美好生活" ) ;
}
}
}
}
class Watcher extends Thread {
Tv tv;
public Watcher ( Tv tv) {
this . tv = tv;
}
@Override
public void run ( ) {
super . run ( ) ;
for ( int i = 0 ; i < 20 ; i++ ) {
tv. watch ( ) ;
}
}
}
class Tv {
String voice;
boolean flag = true ;
public synchronized void play ( String voice) {
if ( ! flag) {
try {
this . wait ( ) ;
} catch ( InterruptedException e) {
e. printStackTrace ( ) ;
}
}
System . out. println ( "表演了:" + voice) ;
this . voice = voice;
this . flag = ! this . flag;
this . notifyAll ( ) ;
}
public synchronized void watch ( ) {
if ( flag) {
try {
this . wait ( ) ;
} catch ( InterruptedException e) {
e. printStackTrace ( ) ;
}
}
System . out. println ( "观看了" + voice) ;
this . flag = ! this . flag;
this . notifyAll ( ) ;
}
}