多线程案例 Java

版权声明:ByRisonBoy https://blog.csdn.net/Rison_Li/article/details/83214400

1、购票(不安全策略)

代码片段:

public class Main {
    private static int ticket = 10;
    public static void main(String[] args) {
    	Runnable r = new Runnable() {
    		public void run() {
    			while(ticket > 0) {
    				try {
    					ticket--;
    					Thread.sleep(1000);
    					System.out.println("卖出了一张票,还剩下"+ticket+"张票");
    				}catch (Exception e) {
    					e.printStackTrace();
    				}
    				
    			}
    		}
    	};
    	new Thread(r).start();
    	new Thread(r).start();
    	new Thread(r).start();
    	new Thread(r).start();
    }
}

显示结果:

卖出了一张票,还剩下6张票
卖出了一张票,还剩下5张票
卖出了一张票,还剩下5张票
卖出了一张票,还剩下5张票
卖出了一张票,还剩下2张票
卖出了一张票,还剩下2张票
卖出了一张票,还剩下2张票
卖出了一张票,还剩下2张票
卖出了一张票,还剩下0张票
卖出了一张票,还剩下0张票

2、购票(安全策略)

  • 给方法加入synchronized解决线程不安全问题

代码片段:

public class Main {
    private static int ticket = 10;
    public static void main(String[] args) {
    	Runnable r = new Runnable() {
    		public synchronized void run() {
    			while(ticket > 0) {
    				try {
    					ticket--;
    					Thread.sleep(1000);
    					System.out.println("卖出了一张票,还剩下"+ticket+"张票");
    				}catch (Exception e) {
    					e.printStackTrace();
    				}
    				
    			}
    		}
    	};
    	new Thread(r).start();
    	new Thread(r).start();
    	new Thread(r).start();
    	new Thread(r).start();
    }
}

显示结果:

卖出了一张票,还剩下9张票
卖出了一张票,还剩下8张票
卖出了一张票,还剩下7张票
卖出了一张票,还剩下6张票
卖出了一张票,还剩下5张票
卖出了一张票,还剩下4张票
卖出了一张票,还剩下3张票
卖出了一张票,还剩下2张票
卖出了一张票,还剩下1张票
卖出了一张票,还剩下0张票

注:第一个线程进入run()后,其他进程无法进入,直到第一个线程执行完毕才允许其他进程进入,而此时ticket已经为0,其他进程不能进入循环体,因此,退出。

其中,形如synchronized (Main.class) {}包含代码块的结构也能达到同样的效果。

3、wait()和notify()

代码片段:

public class Main {
	public static void main(String[] args) {
		new Thread() {
			public void run() {
				synchronized (Main.class) {
					System.out.println("T1 start!");
					try {
						Main.class.wait();
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
					System.out.println("T1 end!");
				}
			}
		}.start();
		new Thread() {
			public void run() {
				synchronized (Main.class) {
					System.out.println("T2 start!");
					Main.class.notify(); //唤醒
					System.out.println("T2 end!");
				}
			}
		}.start();
	}
}

结果显示:

T1 start!
T2 start!
T2 end!
T1 end!

解析:wait()和notify()一系列的方法,是属于对象的,不是属于线程的。它们用在线程同步时,synchronized语句块中。

wait()方法可以使线程进入等待状态,而notify()可以使等待的状态唤醒。这样的同步机制十分适合生产者、消费者模式:消费者消费某个资源,而生产者生产该资源。当该资源缺失时,消费者调用wait()方法进行自我阻塞,等待生产者的生产;生产者生产完毕后调用notify/notifyAll()唤醒消费者进行消费。

4、wait()notify()精细控制

代码片段:

public class Main {
	public static void main(String[] args) {
		final Object object = new Object();
		new Thread() {
			public void run() {
				synchronized (object) {
					System.out.println("T1 start!");
					try {
						object.wait();
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
					System.out.println("T1 end!");
				}
			}
		}.start();
		new Thread() {
			public void run() {
				synchronized (object) {
					System.out.println("T2 start!");
					object.notify();
					System.out.println("T2 end!");
				}
			}
		}.start();;
		new Thread() {
			public void run() {
				synchronized (object) {
					System.out.println("T3 start!");
					object.notify();
					System.out.println("T3 end!");
				}
			}
		}.start();;
		new Thread() {
			public void run() {
				synchronized (object) {
					System.out.println("T4 start!");
					try {
						object.wait();
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
					System.out.println("T4 end!");
				}
			}
		}.start();
	}
}

结果显示:

T1 start!
T2 start!
T2 end!
T1 end!
T3 start!
T3 end!
T4 start!

很容易看出来,T4,它启动了,但是wait了,后面已经没有线程了,它的wait永远不会有线程帮它notify了!于是,T4 (T4 end!没法执行到)它就这么等着!
 

猜你喜欢

转载自blog.csdn.net/Rison_Li/article/details/83214400