多线程访问共享的资源对象,为了避免错误,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();
}
}
}
}