java多线程同步的例子

多线程访问共享的资源对象,为了避免错误,java提供三种解决机制

  • 同步代码块 synchronized code block
  • 同步方法 synchronized method
  • 同步锁 ReentrantLock

package com.linchengshen._01.thread;

//针对多线程并发访问共享资源出现的问题,有三种解决方案

//1.同步代码块
//2.同步方法
//3.锁机制

//下面演示第一种方法,同步代码块,也叫同步锁,互斥锁等名字
//使用synchronized关键字synchronized(mutex),mutex表示需要监听,加锁的资源.
//千万不能用synchronized修饰run方法
public class SynchronizeBlockDemo {
	public static void main(String[] args) {
		test1();
	}

	private static void test1() {
		// TODO Auto-generated method stub
		Apple1 apple1 = new Apple1();
		new Thread(apple1, "小A").start();
		new Thread(apple1, "小B").start();
		new Thread(apple1, "小C").start();
	}
}

class Apple1 implements Runnable {
	private int apple = 500;

	@Override
	public void run() {
		// TODO Auto-generated method stub
		for (int i = 0; i < 500; i++) {
			synchronized (this) {//同步代码块
				if (apple > 0) {
					System.out.println(Thread.currentThread().getName() + "吃了编号为" + apple + "的苹果");
					try {
						Thread.sleep(10);//进程休眠10ms
					} catch (InterruptedException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
					apple--;
				}
			}
		}

	}
}
package com.linchengshen._01.thread;

public class SynchronizedMethodDemo {
	public static void main(String[] args) {
		test1();
	}

	private static void test1() {
		// TODO Auto-generated method stub
		Apple2 apple2 = new Apple2();
		new Thread(apple2, "小A").start();
		new Thread(apple2, "小B").start();
		new Thread(apple2, "小C").start();
	}
}

class Apple2 implements Runnable {
	private int apple = 500;

	@Override
	public void run() {
		// TODO Auto-generated method stub
		for (int i = 0; i < 500; i++) {
			eat();
		}
	}

	//需要加锁的资源
	//run方法不能加synchronized,解决方法是定义一个新的方法
	//synchronized保证了原子操作的同步,不被其他线程干扰
	synchronized private void eat() {
		// TODO Auto-generated method stub

		if (apple > 0) {
			System.out.println(Thread.currentThread().getName() + "吃了编号为" + apple + "的苹果");
			try {
				Thread.sleep(10);//进程休眠10ms,模拟网络延时.
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			apple--;
		}

	}
}
package com.linchengshen._01.thread;

import java.util.concurrent.locks.ReentrantLock;

//通过第三种机制实现线程访问共享资源的锁定操作.
//Lock 接口的ReentrantLock实现类
//使用方法是创建一个ReentrantLock lock对象,使用try{}catch(){}finally{}代码块,
//进入需要同步的操作即可上锁lock.lock();
//在finally代码块中

//场景是三个同学吃苹果,吃的时候,应该先展示手上的苹果编号,然后"吃掉",即apple--;
public class LockDemo {
	public static void main(String[] args) {
		Runnable apple3 = new Apple3();
		new Thread(apple3, "小A").start();
		new Thread(apple3, "小B").start();
		new Thread(apple3, "小C").start();
	}
}

class Apple3 implements Runnable {
	private int apple = 5000;
	private ReentrantLock lock = new ReentrantLock();

	@Override
	public void run() {
		// TODO Auto-generated method stub
				lock.lock();
				try {
					for (int i = 0; i < 5000; i++) {
						eat();
					}
				} finally
		
				{
					lock.unlock();
				}
//		for (int i = 0; i < 500; i++) {
//			eat();
//		}
	}

	synchronized private void eat() {
		// TODO Auto-generated method stub
		if (apple > 0) {
			System.out.println(Thread.currentThread().getName() + "----" + apple);
			try {
				Thread.sleep(1);
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			apple--;
		}
	}
}
如有错误,请斧正.谢谢!
package com.linchengshen._01.thread;

//演示创建线程的两种常见方式
//java中,Thread类及其子类才能成为线程
//方式:继承Thread类,并且覆盖其中的run方法.启动线程用start,不能用run.用run只能当普通方法调用,不会启动线程.
//线程的执行的结果具有不可预知性,有JVM负责线程的调度.
//场景:用户一边听音乐,一边玩游戏
class PlayMusicThread extends Thread {

	PlayMusicThread() {
		super();
	}

	/* (non-Javadoc)
	 * @see java.lang.Thread#run()
	 */
	@Override
	public void run() {
		for (int i = 0; i < 50; i++) {
			System.out.println("正在听音乐" + i);
		}
	}

}

//通过实现Runnable接口来创建线程.
class PlayGameThread implements Runnable {

	@Override
	public void run() {
		// TODO Auto-generated method stub
		for (int i = 0; i < 50; i++) {
			System.out.println("正在玩游戏" + i);
		}
	}
}

public class ExtendsTrheadDemo {
	public static void main(String[] args) {
		//test1();
		//test2();
		//test3();
		test4();
	}

	//还有这种方式创建匿名内部类,是new 父类Thread方式创建匿名内部类对象的简写
	private static void test4() {
		// TODO Auto-generated method stub
		for (int i = 0; i < 50; i++) {
			System.out.println("正在听音乐" + i);
			if (i == 10) {
				new Thread() {
					@Override
					public void run() {
						// TODO Auto-generated method stub
						for (int i = 0; i < 50; i++) {
							System.out.println("正在学习" + i);
						}
					}
				}.start();
			}
		}
	}

	private static void test3() {
		// TODO Auto-generated method stub
		for (int i = 0; i < 50; i++) {
			System.out.println("正在听音乐" + i);
			if (i == 10) {
				new Thread(new Runnable() {//创建匿名内部类

					@Override
					public void run() {
						// TODO Auto-generated method stub
						for (int i = 0; i < 50; i++) {
							System.out.println("播放电影" + i);
						}
					}

				}).start();
			}
		}
	}

	@SuppressWarnings("unused")
	private static void test2() {
		// TODO Auto-generated method stub
		for (int i = 0; i < 50; i++) {
			System.out.println("正在听音乐" + i);
			if (i == 10) {
				Thread th = new Thread(new PlayGameThread());
				th.start();
			}
		}
	}

	//继承Thread方式类创建线程并执行.
	@SuppressWarnings("unused")
	private static void test1() {
		// TODO Auto-generated method stub
		for (int i = 0; i < 50; i++) {
			System.out.println("正在玩游戏" + i);
			if (i == 10) {//创建听音乐的线程并启动
				PlayMusicThread p = new PlayMusicThread();
				p.start();
			}
		}
	}
}

你可能感兴趣的:(java)