Java第十八天(三)
线程
并发(线程同步)
采用实现Runable接口的方式实现
由于是使用实现Runnable接口的方式实现,所以在获取线程名时不能直接获取,需使用Thread类的静态方法。
当只有一个代码块使用一把锁时
线程类
public class SealTicketsThread implements Runnable{
// 由于使用实现Runnable接口的方式,以至于票数这个数据被线程共享,所以这里是对象的属性(成员变量)
private int ticketsCount = 50;
// 由于使用实现Runable接口的方式,以至于同步锁对象被线程共享,所以这里是对象的属性(成员变量)
// 创建同步锁锁的对象
private Object obj = new Object();
/**
* 重写run方法进行售票
*/
@Override
public void run() {
while(true) {
// 这里使用同步锁将并发代码锁起来
synchronized (obj) {
if(ticketsCount > 0) {
System.out.println(Thread.currentThread().getName()+"正在出售第"+ ticketsCount-- +"张票");
}else {
System.out.println(Thread.currentThread().getName()+"票已售完!");
break;
}
}
}
}
}
测试类
public class SealTicketsTest {
public static void main(String[] args) {
/**
* 创建售票类的对象,相当于是票
*/
SealTicketsThread sth1 = new SealTicketsThread();
// 这里使用支持自定义线程名的Thread构造器,相当于是窗口
Thread th1 = new Thread(sth1,"窗口1");
Thread th2 = new Thread(sth1,"窗口2");
Thread th3 = new Thread(sth1,"窗口3");
Thread th4 = new Thread(sth1,"窗口4");
// 启动线程
th1.start();
th2.start();
th3.start();
th4.start();
}
}
当不同的代码块使用同一把同步锁时,不会发生并发异常。
线程类
/**
* 当同步锁为任意类对象时,让不同的代码块使用同一把同步锁
*/
public class SealTicketsThreadSameLock implements Runnable{
// 由于使用实现Runnable接口的方式,以至于票数这个数据被线程共享,所以这里是对象的属性(成员变量)
private int ticketsCount = 500;
// 由于使用实现Runable接口的方式,以至于同步锁对象被线程共享,所以这里是对象的属性(成员变量)
// 创建同步锁锁的对象
private Test2 test2 = new Test2();
/**
* 重写run方法进行售票
*/
@Override
public void run() {
while(true) {
int i = 0;
// 考虑奇偶情况来分别执行不同的代码块
if(i%2 == 0) {
// 这里使用同步锁将并发代码锁起来
synchronized (test2) {
if(ticketsCount > 0) {
System.out.println(Thread.currentThread().getName()+"正在出售第"+ ticketsCount-- +"张票");
}else {
System.out.println(Thread.currentThread().getName()+"票已售完!");
break;
}
}
}else {
// 这里使用相同的同步锁将并发代码锁起来
synchronized (test2) {
if(ticketsCount > 0) {
System.out.println(Thread.currentThread().getName()+"正在出售第"+ ticketsCount-- +"张票");
}else {
System.out.println(Thread.currentThread().getName()+"票已售完!");
}
}
}
i++;
}
}
}
class Test2{
}
测试类
public class SealTicketsTest {
public static void main(String[] args) {
/**
* 创建售票类的对象,相当于是票
*/
SealTicketsThreadSameLock sth = new SealTicketsThreadSameLock();
// 这里使用支持自定义线程名的Thread构造器,相当于是窗口
Thread th1 = new Thread(sth,"窗口1");
Thread th2 = new Thread(sth,"窗口2");
Thread th3 = new Thread(sth,"窗口3");
Thread th4 = new Thread(sth,"窗口4");
// 启动线程
th1.start();
th2.start();
th3.start();
th4