您的位置:首页 > Web前端

java基础专栏—ThreadSafe

2017-10-21 00:00 148 查看
摘要: 笔者在java学习的这条道路上也是断断续续走了一年多了,视频啊,书籍啊什么的也看了好几遍了,真的是java从入门到放弃啊,哈哈,看的多了一渐渐的明白了一点东西,笔者整理了一些自己的学习笔记,在此与大家分享,不喜勿喷,多多指教,万分感谢。

ThreadSafe

多线程并发

public class Tickets implements Runnable{
private int ticket = 100;

public void run(){
while(true){
if(ticket > 0){
System.out.println(Thread.currentThread().getName() + "出售票" + ticket--);
}
}
}
}
pubilc static void main(String[] args){
Tickets ts = new Ticket();

Thread t0 = new Thread(ts);
Thread t1 = new Thread(ts);
Thread t2 = new Thread(ts);

t0.start();
t1.start();
t2.start();
}

同步代码块解决线程问题:
synchronized(Object obj){线程要操作的代码块}


private Object obj = new Object();
public void run(){
while(true){
synchronized(obj){
if(ticket > 0){
System.out.println(Thread.currentThread().getName() + "出售票" + ticket--);
}
}
}
}

同步对象:
任意对象,对象监听器

没有锁的线程不能执行只能等待,遇见同步代码块,

判断对象锁还有没有

有,拿走,等执行完成才放回去

没有就只有等

将线程共享部分抽取出来

private int ticket = 100;
public void run(){
while(true){
pay();
}
}
}
public static synchronized void pay(){
if(ticket > 0){]
System.out.println(Thread.currentThread().getName() + "出售票" + ticket--);
}
//在同步方法中,对象锁是this。但是在静态方法中,对象锁不是this,this属于对象,优先于static,是本类自己.class

Lock

​ 在线程中,只有出了同步代码块才会释放对象锁,但是要是出现了异常就不会释放了。所以在jdk5以后就使用
Lock接口


public void lock()

public void unlock()

死锁问题

锁的嵌套
出现了互锁

确保锁唯一

构造方法私有,只能通过静态方法来调用,且不可修改

public class lockA{
public static final LockA lockA = new LockA();

private LockA(){

}
}

public class lockB{
public static final LockB lockB = new LockB();

private LockB(){

}
}

public class DeadLock implements Runnable{
private int i = 0;

public void run(){
while(ture){
if(i%2 == 0){
//先进入A同步,在进入B同步
synchronized(LockA.locka){
System.out.println("if...locka");
synchronized(LockB.lockb){
System.out.println("else...lockb");
}
}
}else{
synchronized(LockB.lockb){
System.out.println("if...lockb");
synchronized(LockA.locka){
System.out.println("else...locka");
}
}
}
}
}
}

线程间通信

​ 多个线程操作同一个数据,但是操作的动作可能并不相同,通过一定的手段将各个线程有效的利用,既--等待唤醒机制

public void wait()释放正在执行的线程的执行权,放到存储池

public void notify()唤醒在线程池中wait()的线程,一次唤醒一个,而且是任意的。

public void notifyAll(),唤醒在线程池中所有的wait()线程唤醒

[x] 线程之间是不是所有的数据都锁上了

[x] 是不是用的同一个锁

public class Resource{
public String name;
public String sex;
public boolean flag;//唤醒标识

public Resource(String name,String sex){
this.name = name;
}
}

public class InputThread implements Runnable{
private Resource r = null;
public InputThread(Resource r){
this.r = r;
}
public void run(){
int i = 0;
while(true){
synchronized(r){
if(r.flag){
try{
//必须是锁对象调用
r.wait();
}catch(Exception ex){
System.out.println(ex.getMessage());
}
}
if(i%2 == 0){
r.name = "张三";
r.sex = "男";
}else{
r.name = "lisi";
r.sex = "nv";
}
i++;
//执行完成,将标识修改,并唤醒对方。
r.flag = true;
r.notify();
}
}
}
}

public class OutputThread{
private Resource r = null;
public void run(){
//使用同一个对象锁
synchronized(r){
while(true){
if(r.flag){
try{
//必须是锁对象调用
r.wait();
}catch(Exception ex){
System.out.println(ex.getMessage());
}
System.out.println(r.name);
//执行完成,将标识修改,并唤醒对方。
r.flag = false;
r.notify();
}
}
}
public OutputThread(Resource r){
this.r = r;
}
}

public class ThreadDemo{
public static void main(String[] args){
Resource r = new Resource();
InputThread int = new InputThread(r);
OutputThread outt = new OutputThread(r);

Thread in = new Thread(in);
Thread out = new Thread(out);
}
}

为什么是Object的方法

​ 对于线程来说,要同步必须操作同一个
锁对象
才可以,如果是使用各自来做自己的线程唤醒对象就不能实现
同一个锁对象
,并且对于实现类来说,调用者是谁?

​ ==所有的线程的等待唤醒必须是锁对象调用,调用者是谁?任何方法都需要被调用,本类线程类是没有wait方法的,只有调用父类的super(),但是父类也没有这个方法,调用这个的锁对象是谁就由谁来调用,所以,同步的等待唤醒方法都是Object类的方法==
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  java thread threadpool