1.使用同步代码块
synchronized(锁){
需要被同步的代码
}
注意:锁可以是任意对象,锁是唯一的。
同步在目前情况下保证了一次只能有一个线程在执行,其他的线程进不来。
同步代码块规则:
当线程进入同步代码块的时候,先看一下有没有锁,如果有锁,就进入同步代码块中执行代码。进去的同时会获取这把锁,当代码执行完毕,出同步代码块时,将这把锁释放。如果没锁,线程在同步代码块前等待,有锁才进入。
好处:解决了多线程的安全问题。
弊端:降低了效率。
/*
* 同步方法(作用和同步代码块相同)
* 也是用synchronized关键字
* 该关键字 声明在方法上
* 同一时间 只能有一个线程 进入到同步方法中 执行代码
* 同步方法中 也是写操作共享数据的代码
*/
public class Demo02 {
public static void main(String[] args) {
// 创建3个线程
TicketRunnable1 runnable1 = new TicketRunnable1();
Thread t1 = new Thread(runnable1);
Thread t2 = new Thread(runnable1);
Thread t3 = new Thread(runnable1);
// 开启线程
t1.start();
t2.start();
t3.start();
}
}
// 接口实现线程
class TicketRunnable1 implements Runnable {
// 声明50个票
private static int ticket = 50;
// 声明锁对象(保证只有一把锁)
private Object object = new Object();
// 卖票 票--
@Override
public void run() {
while (true) {
if (sellTicket()) {
break;
}
Thread.yield();
}
}
//声明同步方法
//同步方法时怎么处理的的 有没有锁 锁是什么
//有锁 处理方式和 同步代码块一样
//同步的对象(成员)方法 锁是 this(本类的对象)
//静态方法能不能加锁? 能
//静态方法的锁是this吗 静态方法不能使用this
//静态方法使用的锁是 类锁 类名.class
//
private synchronized static boolean sellTicket() {
if (ticket > 0) {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + "***" + ticket);
ticket--;
//返回值 用作循环判断停止
return false;
} else {
return true;
}
}
}
JDK 1.5出现的Lock接口
使用实现类 ReentrantLock
lock() 获取锁
unlock()释放锁
使用前提:和同步代码块一样 要保证 用的是 同一把锁
使用格式:
try{
操作共享数据的代码
}finally{
释放锁
}
public class Demo03 {
public static void main(String[] args) {
// 创建3个线程
TicketRunnable2 runnable2 = new TicketRunnable2();
Thread t1 = new Thread(runnable2);
Thread t2 = new Thread(runnable2);
Thread t3 = new Thread(runnable2);
// 开启线程
t1.start();
t2.start();
t3.start();
}
}
class TicketRunnable2 implements Runnable {
private int ticket = 50;
//声明锁 保证同一把
private ReentrantLock lock = new ReentrantLock();
@Override
public void run() {
while (true) {
//获取锁
lock.lock();
try {
if (ticket > 0) {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + "***" + ticket);
ticket--;
} else {
break;
}
} finally {
lock.unlock();
}
Thread.yield();
}
}
}
线程的停止:
stop()方法 已经过时,不推荐使用。
interrupt()方法 中断线程
interrupt方法的作用:
1.调用interrupt方法时,线程中有wait(),sleep()等方法,这时会抛出一个InterruptException异常,并且清楚中断。
2.调用interrupt方法时,线程中没有上述方法,这时会设置(改变)中断状态的值(true---false)。
public class Test {
public static void main(String[] args) throws InterruptedException {
TestRunnable runnable = new TestRunnable();
Thread t1 = new Thread(runnable);
t1.start();
t1.interrupt();
}
}
class TestRunnable implements Runnable {
@Override
public void run() {
while (!Thread.interrupted()) {
System.out.println("我是子线程" + ".......run");
}
}
}