多线程之同步锁 加锁和线程停止

一.同步代码块(同步锁)
写法:
synchronized(锁){
上锁的代码
}
当线程进入同步代码块 会把锁拿走 执行代码块中的代码
代码执行完毕后 会把锁还回去
如果线程遇到同步代码块 发现没有锁 将进入等待(有锁才可进)

锁的注意:保证所有线程使用的是同一个锁 锁可以使用任意一个对象(同一个对象就行)
public class Demo01 {
public static void main(String[] args) {
//利用接口的实现类 创建三个线程出来
Tickets tickets=new Tickets();
Thread t1=new Thread(tickets);
Thread t2=new Thread(tickets);
Thread t3=new Thread(tickets);
t1.start();
t2.start();
t3.start();
}
}
class Tickets implements Runnable {
private int tickets = 30;
// 声明锁的对象
private final Object obj = new Object();
public void run() {
// 利用循环
while (true) {
synchronized (obj) {
// 休眠
try {
Thread.sleep(100);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
// 判断
if (tickets > 0) {
System.out.println(Thread.currentThread().getName() + "" + tickets);
tickets–;
} else {
break;
}
}
//让线程让出cpu的执行资源
Thread.yield();
}
}
}
二.加锁和释放锁
lock();加锁方法
unlock();释放锁方法
保证出现异常时也能把锁关闭
写法:lock();
try{
加锁的代码
}finaly{
释放锁
unlock();
}
public class Demo2 {
public static void main(String[] args) {
Tickets2 tickets=new Tickets2();
//创建三个线程
Thread t1=new Thread(tickets);
Thread t2=new Thread(tickets);
Thread t3=new Thread(tickets);
t1.start();
t2.start();
t3.start();
}
}
//利用接口方法
class Tickets2 implements Runnable {
private int tickets = 10;
// 声明锁的对象
private final Object obj = new Object();
//声明lock锁
//参数 :true 可以让线程尽量公平加入锁
private final ReentrantLock lock =new ReentrantLock(true);
public void run() {
// 利用循环
while (true) {
//使用lock锁
lock.lock();
try {
if (tickets>0) { System.out.println(Thread.currentThread().getName()+"
"+tickets);
tickets–;
}else {
break;
}
} finally {
//释放锁
lock.unlock();
}
Thread.yield();
}
}
}
三.死锁
前提:至少是两个线程 锁的嵌套(同步代码块的嵌套)
public class Demo03 {
public static void main(String[] args) {
test1Thread test=new test1Thread();
Thread t1=new Thread(test);
Thread t2=new Thread(test);
t1.start();
t2.start();
}
}
//声明锁
class LockA{
//私有化构造方法
private LockA() {
}
//创建锁对象
public static final LockA A_=new LockA();
}
class LockB{
//私有化构造方法
private LockB() {
}
//创建锁对象
public static final LockB B_=new LockB();
}
//线程
class test1Thread implements Runnable{
//利用标记来控制先A->B或先B->A
boolean isture=false;
public void run() {
//利用死循环
while (true) {
//让两个线程不断的先进A锁再进B锁 下一次从B进A锁
if (!isture) {
//先进A再进B(同步代码块嵌套)
synchronized (LockA.A_) {
System.out.println(“if中的A锁”);
synchronized (LockB.B_) {
System.out.println(“if中的B锁”);
}
}
} else {
//下次从B进A
synchronized (LockB.B_) {
System.out.println(“else中的B锁”);
synchronized (LockA.A_) {
System.out.println(“else中的A锁”);
}
}
}
//改变一下标记
isture=!isture;
}
}
}
四.线程停止
调用Stop方法 已经过时 不推荐使用
interrupt()方法 不能中断线程 中断状态将被设置
interrupt()方法 1.可以改变中断状态 是个布尔值 初值false->true
2.当此线程中 使用sleep wait join方法时 会抛出中断异常 中断状态将被清除 此时interrupted()的值还是false
直接使用标记停止线程
public class Demo04 {
public static void main(String[] args) {
interruptedRunnable iRunnable=new interruptedRunnable();
Thread t=new Thread(iRunnable);
t.start();
//休眠几秒
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
//中断线程
//t.interrupt();
//利用标记停止线程
iRunnable.istrue=true;
System.out.println("线程中断
**");
//主线程继续运行
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println(“主线程结束”);
}
}
class interruptedRunnable implements Runnable{
//声明一个标记 控制线程的停止
public boolean istrue=false;
public void run() {
while (!istrue) {
/* long timeMillis = System.currentTimeMillis();
while (System.currentTimeMillis()-timeMillis<1000) {

	}   */
	try {
		//抛出中断异常
		//中断状态被清除指的是从休眠状态-->运行状态(或者受阻塞)
		Thread.sleep(1000);
	} catch (InterruptedException e) {
		e.printStackTrace();
	}
	System.out.println(Thread.currentThread().getName()+"run");
}	
}

}

猜你喜欢

转载自blog.csdn.net/chenyuanshengboke/article/details/82779215