同步锁的理解以及转变安全集合的方法

多线程的实现步骤 :从开始创建的时候到线程的执行,最终到线程的终止

1)新建线程:没有执行资格,没有执行权

2)线程就绪:有执行资格,但没有执行权

(这里可能也会发生线程阻塞状态:线程睡眠或者等待)

3)线程执行:有执行资格并且有执行权

4)线程死亡:线程执行完毕,会被垃圾回收线程中的垃圾回收器及时的从内存中释放掉

当我们运行多线程模仿现实窗口售票应该怎么做?

例如:

使用实现Runnable方式

package com.westos.Runnable;
 
public class MyRunnable implements Runnable{
 
/**
 * 同步锁的对象可以是任意的java类对象
 * 例如我们在下方定义一个Dome类,并在此创建Dome类对象
 * 然后将同步锁的对象换成Dome类对象,依旧可以模拟现实窗口售票
 */
private Dome d=new Dome();
//定义一个私有公用的票数变量
private static int tickets=100;
定义同一把锁对象
//private Object obj=new Object();
@Override
public void run() {
while(true) {
/**
 * 为了多个线程可以享用到共享资源我们必须的设置同一把锁,不然依旧会出现好几个窗口在出售同一张票的情况
 * 这里的synchronized()方法就好比是一扇门,当其中的一个线程进来后就会关闭这扇门,然后去享受资源
 * 等它享受完后,下一个线程会继承抢着进来享受资源,每一线程进来后
 * 共享代码块就会发挥它的作用,这样就不会出现同票和负票的现象了
 */
synchronized (d) {
if(tickets>0) {
//模范现实售票延迟的效果,给线程加入睡眠的功能(睡眠100毫秒)
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
//因为上面是运用了实现Runnable接口的方法,不能直接调用getName方法,当你使用继承Thread类方式时,就可以使用了
//必须通过Thread类中的返回正在运行的线程的方法再用它去调用getName方法
System.out.println(Thread.currentThread().getName()+"正在出售第"+(tickets--)+"张票");
}
}
}
}
class Dome{

}
}

 

创建一个测试类

package com.westos.Runnable;
/**
 * 当我们模拟现实售票的情况时,会出现窗口出售同一张票的情况以及出现负票的情况
 * (例如窗口1正在出售第0张票或者窗口1正在出售第-1张票的情况)
 *解决方法:
 * 将我们的共享数据用同步代码块包起来
 * 格式synchronized(锁对象){
 * 多条语句对共享数据的使用代码
 * }
 *
 */
public class RunnableDome {
 
public static void main(String[] args) {

//创建资源类对象
MyRunnable my=new MyRunnable();

//创建Thread类对象
Thread t1=new Thread(my,"窗口1");
Thread t2=new Thread(my,"窗口2");
Thread t3=new Thread(my,"窗口3");

//执行线程
t1.start();
t2.start();
t3.start();
}
}

 

当我们把同步锁放在方法中以及放在方法上时,依旧可以去模拟现实中窗口售票

切记:

当方法是静态时,记住要锁对象是该类名.class

例如:

package com.westos.Runnable;
 
public class SellTicket implements Runnable{

//创建Dome类对象
Dome d=new Dome();

//定义一个通用的票数
private static int ticket=100;
//定义一个变量
private int x=0;

@Override
public void run() {
 
//循环
while(true) {
if(x%2==0) {
synchronized (SellTicket.class) {//当方法时静态时:锁对象:类名.class;  当方法不是静态时,锁对象是this
if(ticket>0) {
//让共享资源睡眠0.1秒
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+"正在出售第"+(ticket--)+"张票");
}
}
}
else {
sellTicket();
}
x++;
}
}

//我们可以将同步锁写在方法中,然后在run方法中调用即可
/*private void sellTicket() {
 
synchronized (d) {
if(ticket>0) {
//让共享资源睡眠0.1秒
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+"正在出售第"+(ticket--)+"张票");
}
}
}*/

//或者我们可以直接把同步锁写在方法上去调用
//当该方法时静态的时候,该类中的锁对象是类名.class
private  synchronized static void sellTicket() {
 
if(ticket>0) {
//让共享资源睡眠0.1秒
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+"正在出售第"+(ticket--)+"张票");
}
}
class Dome{

}
}

 

 

package com.westos.Runnable;
 
public class SellTicketDome {
 
public static void main(String[] args) {

//创建资源类对象
SellTicket st=new SellTicket();

//创建三个Thread类对象
Thread t1=new Thread(st,"窗口1");
Thread t2=new Thread(st,"窗口2");
Thread t3=new Thread(st,"窗口3");

//启动线程
t1.start();
t2.start();
t3.start();
}
}
运行结果:
窗口2正在出售第7张票
窗口3正在出售第6张票
窗口1正在出售第5张票
窗口1正在出售第4张票
窗口3正在出售第3张票
窗口3正在出售第2张票
窗口3正在出售第1张票

 

 

我们目前学习了线程安全的类有三个:

StringBuffer缓冲区、Vector集合、Hashtable集合

接下来让我们学习一种将线程不安全的类转换成线程安全类的方法

 

例如:

package com.westos.synchronizedList;
 
import java.util.ArrayList;
import java.util.Collections;
import java.util.Hashtable;
import java.util.List;
import java.util.Vector;
 
public class synchronizedListDome {
 
public static void main(String[] args) {

//目前我们学习过的线程安全的类有:
StringBuffer sb=new StringBuffer();
Vector v=new Vector();
Hashtable ht=new Hashtable();

/**
 * 但是当我们运用一些集合的时候还是习惯用ArrayList集合
 * 所以我们应该怎么将一些线程不安全的类转变成线程安全 的类呢
 * 接下来就需要运用到collections工具类的synchronizedList方法了
 */
//创建ArrayList集合对象,将类型定为String类型
ArrayList<String> list=new ArrayList<String>();
//调用方法://public static <T> List<T> synchronizedList(List<T> list)
//返回是List集合,返回的集合就是线程安全的类了
List<String> array = Collections.synchronizedList(list);
}
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值