线程同步:(定义)当多个线程使用同一对象中被同步的资源时,要根据“先来后到”的顺序使用。
线程异步:(定义)当多个线程使用同一对象中被同步的资源时,可以同时使用(例如:电脑这一同意对象,可以播放音乐和敲代码同时进行)
线程同步之同步块和同步方法:
1. 同步的关键字:synchronized
2. 同步方法的格式:【访问修饰符】 synchronized 返回值类型 方法名(【参数列表】){}
3. 同步块的格式:synchronized(对象){}
4. 使用同步的原则是:尽可能的缩小同步的范围
小案例(同步方法或同步块)如下:
(题目内容):四个人使用同一台电脑,分别用来玩游戏、玩游戏、敲代码和听音乐,使用同步线程来四个人的玩游戏、敲代码和听音乐。并创建一个测试类来测试线程同步。
同步方法
案例的实体类(同步的对象)代码如下:
package com.computer.entity;
public class Computer {
//玩游戏
//同步方法:使用关键字修饰的方法,就是同步的方法
//多个线程同时访问同一个Computer对象上的同步方法,必须要有"先来后到"的顺序
public synchronized void playGame(){
System.out.println("游戏开始");
try {
//模拟玩游戏的时间
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("游戏结束");
}
//敲代码
public synchronized void coding(){
System.out.println("代码开始");
try {
//模拟敲代码的时间
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("代码结束");
}
//听音乐
public void listing(){
System.out.println("音乐开始");
try {
//模拟听音乐的时间
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("音乐结束");
}
}
其中游戏A的线程的代码如下:
package com.thread;
import com.computer.entity.Computer;
public class ThreadGameA extends Thread{
public Computer computer;
public ThreadGameA(Computer computer) {
this.computer = computer;
}
public void run(){
computer.playGame();
}
}
游戏B、敲代码和听音乐的代码和游戏A的代码类似,这里就不在叙述了
测试代码线程同步的代码如下:
package com.test;
import com.computer.entity.Computer;
import com.thread.ThreadCodingB;
import com.thread.ThreadGameA;
import com.thread.ThreadGameB;
import com.thread.ThreadListingC;
public class TestComputer {
public static void main(String args[]){
//创建一台电脑
Computer com = new Computer();
ThreadGameA gameA = new ThreadGameA(com);
ThreadGameB gameB = new ThreadGameB(com);
ThreadCodingB code = new ThreadCodingB(com);
ThreadListingC listen = new ThreadListingC(com);
//启动线程
gameA.start();
gameB.start();
code.start();
listen.start();
}
}
同步块
案例的实体类(同步的对象)代码如下:
package com.computer.entity;
public class Computer {
//玩游戏
public void playGame(){
System.out.println("游戏开始启动");
try {
//模拟游戏启动的时间
Thread.sleep(1000);
} catch (InterruptedException e1) {
e1.printStackTrace();
}
System.out.println("游戏启动成功");
//同步块:将代码中的一部分同步起来,使用关键字synchronized
//同步块的原则:尽可能少的同步代码块
synchronized (this) {
System.out.println("游戏开始");
try {
//模拟玩游戏的时间
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("游戏结束");
}
}
//敲代码
public void coding(){
System.out.println("启动MyEclipse");
try {
//模拟MyEclipse启动的时间
Thread.sleep(1000);
} catch (InterruptedException e1) {
e1.printStackTrace();
}
System.out.println("MyEclipse启动成功");
synchronized(this){
System.out.println("代码开始");
try {
//模拟敲代码的时间
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("代码结束");
}
}
//听音乐
public void listing(){
System.out.println("开始启动网易云音乐");
try {
//模拟开启网易云音乐的时间
Thread.sleep(1000);
} catch (InterruptedException e1) {
e1.printStackTrace();
}
System.out.println("网易云音乐启动成功");
System.out.println("音乐开始");
try {
//模拟听音乐的时间
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("音乐结束");
}
}
游戏A、游戏B、敲代码和听音乐的代码以及测试线程同步的代码和同步方法中的代码相同,这里就不在叙述了