Java多线程(一):
https://blog.csdn.net/Veer_c/article/details/103842078
Java多线程(二):
https://blog.csdn.net/Veer_c/article/details/103842263
Java多线程(三):
https://blog.csdn.net/Veer_c/article/details/103842317
Java多线程(四):
https://blog.csdn.net/Veer_c/article/details/103842602
案例:利用匿名内部类,启动多个线程,验证单例设计模式之懒汉式所存在的缺陷,
public class SingleIntanceDemo {
//私有化构造
private SingleIntanceDemo(){}
private static SingleIntanceDemo instance = null;
public static SingleIntanceDemo getInstance(){
try {
Thread.sleep(100);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
if (instance==null) {
instance = new SingleIntanceDemo();
}
return instance;
}
}
public class Test {
public static void main(String[] args) {
//启动第一个线程
new Thread(){
@Override
public void run() {
System.out.println(SingleIntanceDemo.getInstance());
//com.edu_12.SingleIntanceDemo@2d7fc1e7
}
}.start();
//启动第二个线程
new Thread(){
public void run() {
System.out.println(SingleIntanceDemo.getInstance());
//com.edu_12.SingleIntanceDemo@2a8b83e3
};
}.start();
}
}
当我们利用多线程来验证单例模式的时候,发现俩个对象的地址值不同,即不是同一个对象,我们可以利用同步方法来改进
在创建对象的方法上加上 synchronized关键字就可以
(9)JDK5的Lock锁,我们之前造的所有的锁都没有手动释放锁
static Lock lock = new ReentrantLock();
上枷锁:lock.lock();
释放锁:lock.unlock();
可以让我们明确的知道在哪里加锁和释放锁。
依然写一个卖票的案例,用lock枷锁释放锁,
为了保证我们创建的锁一定会被释放,用一下代码进行改进
try{….}finally{……}
public class MyThread implements Runnable{
//定义100张票
int ticket = 100;
Object obj = new Object();
//创建一个锁
Lock lock = new ReentrantLock();
@Override
public void run() {
while (true) {
try{
//加上锁,获取锁
lock.lock();
if (ticket>0) {
//考虑到实际的生活中,我们需要给每一个线程加入一定的延迟,模拟一下这种效果
try {
Thread.sleep(100);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+"正在出售第:"+ticket--+"张票");
}
}finally{
//这里面的代码一定会被执行
//释放锁
lock.unlock();
}
}
}
}
public class Test {
public static void main(String[] args) {
//创建MyThread对象
MyThread mt = new MyThread();
//创建三个窗口
Thread t1 = new Thread(mt);
Thread t2 = new Thread(mt);
Thread t3 = new Thread(mt);
//给每一个窗口设置姓名
t1.setName("窗口一");
t2.setName("窗口二");
t3.setName("窗口三");
//开启窗口进行售票
t1.start();
t2.start();
t3.start();
}
}
死锁问题:
同步嵌套,锁里面套了一个锁,出现同步嵌套
package com.edu_14;
public class DieThread extends Thread{
boolean flag;
//提供一个有参构造
public DieThread(boolean flag){
this.flag = flag;
}
@Override
public void run() {
if (flag) {
synchronized (MyLock.objA) {
System.out.println("if"+"objA");
synchronized (MyLock.objB) {
System.out.println("if"+"objB");
}
}
}else {
synchronized (MyLock.objB) {
System.out.println("else"+"objB");
synchronized (MyLock.objA) {
System.out.println("else"+"objA");
}
}
}
}
}
package com.edu_14;
public abstract class MyLock {
//定义两个锁
public static final Object objA = new Object();
public static final Object objB = new Object();
}
package com.edu_14;
public class Test {
public static void main(String[] args) {
//创建两个线程,分别设置不同的布尔值
DieThread dt = new DieThread(true);
DieThread dt2 = new DieThread(false);
//开启两个线程
dt.start();
dt2.start();
}
}
线程等待和唤醒机制:waitThread,NotifyThread,MyLock,Test
锁对象调用wait() 锁对象调用notify()
package com.edu_15;
public abstract class MyLock {
public static final Object obj = new Object();
}
package com.edu_15;
public class WaitThread extends Thread{
@Override
public void run() {
synchronized (MyLock.obj) {
//让等待线程处于等待状态
try {
MyLock.obj.wait();//当线程处于等待状态的时候,线程就不会继续往下执行了
//线程在处于等待的时候,会释放掉自己手中的锁
//sleep()这个方法,在线程休息的时候会释放锁码?
//答:不会
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
System.out.println("我被唤醒了");
}
}
package com.edu_15;
public class NotifyThread extends Thread{
@Override
public void run() {
synchronized (MyLock.obj) {
//唤醒等待线程
MyLock.obj.notify();//唤醒正在等待的线程,唤醒的等待线程的锁对象,必须和等待线程的锁对象一致
}
}
}
package com.edu_15;
/* (11)线程等待和唤醒机制(案例演示:waitThread,NotifyThread,MyLock,Test)
锁对象调用wait():线程的等待
锁对象调用notify():线程的唤醒
* 注意:
wait和sleep的区别
线程等待,在等待的同时释放锁,而sleep()方法在执行的过程中是不会释放锁的 */
public class Test {
public static void main(String[] args) {
//创建等待线程,让等待线程处于一个等待状态
WaitThread wt = new WaitThread();
wt.start();
//睡上5秒钟之后唤醒等待线程
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
//创建唤醒线程对象
NotifyThread nt = new NotifyThread();
nt.start();
}
}
注意:wait和sleep的区别:
线程等待,在等待的同时释放锁,而sleep()方法在执行的过程中是不会释放锁的
Java多线程(一):
https://blog.csdn.net/Veer_c/article/details/103842078
Java多线程(二):
https://blog.csdn.net/Veer_c/article/details/103842263
Java多线程(三):
https://blog.csdn.net/Veer_c/article/details/103842317
Java多线程(四):
https://blog.csdn.net/Veer_c/article/details/103842602