synchronized:代码开始上锁,代码结束时释放锁;内置锁、自动化的、效率低、扩展性不高(不够灵活);

JDK1.5并发包Lock锁 --保证线程安全问题,属于手动挡,手动开始上锁,手动释放锁,灵活性高;

Lock 接口与 synchronized 关键字的区别

Lock 接口可以尝试非阻塞地获取锁 当前线程尝试获取锁。如果这一时刻锁没有被其他线程获取到,则成功获取并持有锁。

Lock 接口能被中断地获取锁 与 synchronized 不同,获取到锁的线程能够响应中断,当获取到的锁的线程被中断时,中断异常将会被抛出,同时锁会被释放。

Lock 接口在指定的截止时间之前获取锁,如果截止时间到了依旧无法获取锁,则返回。

Lock用法:

Lock写法

Lock lock = new ReentrantLock();

lock.lock();

try{

//可能会出现线程安全的操作

}finally{

//一定在finally中释放锁

//也不能把获取锁在try中进行,因为有可能在获取锁的时候抛出异常

lock.ublock();

}

class Res{

public String username;

public String sex;

//true 生产者等待,消费者可消费 false生产者可以生产,消费者不可消费

public boolean flag=false;

Lock lock=new ReentrantLock();

}

class Out extends Thread{

Res res;

Condition newCondition;

public Out(Res res,Condition newCondition){
this.res=res;
this.newCondition=newCondition;
}
@Override
public void run() {
//写操作
int count=0;
while (true){
try{//防止异常后不释放锁
res.lock.lock();
if(res.flag){
newCondition.await();//让当前线程从运行变为阻塞,并且释放所的资源
}
if(count==0){//偶数
res.username="小明";
res.sex="男";
} else {//奇数
res.username="小红";
res.sex="女";
}
count=(count+1)%2;
res.flag=true;
newCondition.signal();
} catch (Exception e){
} finally {
res.lock.unlock();
}
}
}

}

class Input extends Thread{

Res res;

Condition newCondition;

public Input(Res res,Condition newCondition){

this.res=res;

this.newCondition=newCondition;

}

@Override
public void run() {
while (true){
try{
res.lock.lock();
if(!res.flag){
newCondition.await();//让当前线程从运行变为阻塞,并且释放所的资源
}
System.out.println(res.username+","+res.sex);
res.flag=false;
newCondition.signal();
} catch (Exception e){
} finally {
res.lock.unlock();
}
}
}

}

public class LockDemo {

public static void main(String[] args) {

Res res = new Res();

Condition condition=res.lock.newCondition();

Out out = new Out(res,condition);

Input input = new Input(res,condition);

out.start();

input.start();

}

}

Condition用法:

Condition condition = lock.newCondition();

res. condition.await(); 类似wait

res. Condition. Signal() 类似notify

多线程并发(Thread)操作同一个资源---------网站并发(多个请求同时访问一台服务)

停止线程

停止线程思路

  1. 使用退出标志,使线程正常退出,也就是当run方法完成后线程终止。
2.  使用stop方法强行终止线程;这个方法不推荐使用,因为stop和suspend、resume一样,也可能发生不可预料的结果(没执行完就终止没有记录上次执行点,并且不可恢复,不论你当前什么状况都给你停掉)。

3.  使用interrupt方法中断线程。

那么怎么停止线程比较合适呢?或者说怎么设计一种停止线程的方式?

class StopThreadDemo extends Thread{

private volatile boolean flag=true;

@Override
public void run() {
System.out.println("子线程开始执行......");
while (flag){ }
System.out.println("子线程执行结束......");
}
public void stopThread(){
this.flag=false;
}

}

public class StopThread {

public static void main(String[] args) throws InterruptedException {

StopThreadDemo stopThreadDemo=new StopThreadDemo();

stopThreadDemo.start();

for (int i = 0; i < 10; i++) {

System.out.println("我是主线程,i:"+i);

Thread.sleep(1000);

if(i==6)

stopThreadDemo.stopThread();

}

}

}

我是主线程,i:0

子线程开始执行......

我是主线程,i:1

我是主线程,i:2

我是主线程,i:3

我是主线程,i:4

我是主线程,i:5

我是主线程,i:6

我是主线程,i:7

子线程执行结束......

我是主线程,i:8

我是主线程,i:9

class StopThreadDemo extends Thread{

private volatile boolean flag=true;

@Override
public synchronized void run() {
System.out.println("子线程开始执行......");
while (flag){
try {
wait();
} catch (InterruptedException e) {

// e.printStackTrace();

stopThread();

}

}

System.out.println("子线程执行结束......");

}

public void stopThread(){

this.flag=false;

}

}

public class StopThread {

public static void main(String[] args) throws InterruptedException {

StopThreadDemo stopThreadDemo=new StopThreadDemo();

stopThreadDemo.start();

for (int i = 0; i < 10; i++) {

System.out.println("我是主线程,i:"+i);

Thread.sleep(1000);

if(i==6) {

//当前等待线程直接抛出异常

stopThreadDemo.interrupt();

// stopThreadDemo.stopThread();

}

}

}

}

以上两种方式都可以。。。

可以看到这是一种停止线程的方式

ThreadLocal

ThreadLocal提高一个线程的局部变量,访问某个线程拥有自己局部变量。

线程1和线程2各自操作自己的副本count,互相影响。

当使用ThreadLocal维护变量时,ThreadLocal为每个使用该变量的线程提供独立的变量副本,所以每一个线程都可以独立地改变自己的副本,而不会影响其它线程所对应的副本。

ThreadLocal的接口方法

ThreadLocal类接口很简单,只有4个方法,我们先来了解一下:

void set(Object value)设置当前线程的线程局部变量的值。

public Object get()该方法返回当前线程所对应的线程局部变量。

public void remove()将当前线程局部变量的值删除,目的是为了减少内存的占用,该方法是JDK 5.0新增的方法。需要指出的是,当线程结束后,对应该线程的局部变量将自动被垃圾回收,所以显式调用该方法清除线程的局部变量并不是必须的操作,但它可以加快内存回收的速度。

protected Object initialValue()返回该线程局部变量的初始值,该方法是一个protected的方法,显然是为了让子类覆盖而设计的。这个方法是一个延迟调用方法,在线程第1次调用get()或set(Object)时才执行,并且仅执行1次。ThreadLocal中的缺省实现直接返回一个null。

案例:创建三个线程,每个线程生成自己独立序列号。

class ResNum{

public int count=0;

public static ThreadLocal threadLocal=new ThreadLocal(){

protected Integer initialValue(){

return 0;

}

};

public String getNumber(){
count=threadLocal.get()+1;
threadLocal.set(count);

// count=count+1;

return count+"";

}

}

class LocalThreadDemo extends Thread{

private ResNum resNum;

public LocalThreadDemo(ResNum resNum){

this.resNum=resNum;

}

@Override
public void run() {
for (int i = 0; i < 3; i++) {
System.out.println(getName()+","+resNum.getNumber());
}
}

}

public class ThreadLocalDemo {

public static void main(String[] args) {

ResNum resNum1=new ResNum();

// ResNum resNum2=new ResNum();

// ResNum resNum3=new ResNum();

LocalThreadDemo t1=new LocalThreadDemo(resNum1);

LocalThreadDemo t2=new LocalThreadDemo(resNum1);

LocalThreadDemo t3=new LocalThreadDemo(resNum1);

t1.start();

t2.start();

t3.start();

}

}

多线程之间通讯JDK1.5-Lock的更多相关文章

  1. qt 多线程之间通讯

    问题描述:界面线程MainApp为主线程,工作线程MyThread为一子线程,从工作线程向主线程传递字符串用于在主线程中显示. Qt的信号与槽机制可以将任何继承自QObject类的对象捆绑在一起,使不 ...

  2. 【java】-- 多线程之间实现通讯

    1.多线程之间如何实现通讯 1.1.什么是多线程之间通讯? 多线程之间通讯,其实就是多个线程在操作同一个资源,但是操作的动作不同. 画图演示 1.2.多线程之间通讯需求 需求:第一个线程写入(inpu ...

  3. JAVA多线程-实现通讯

    一.多线程之间如何实现通讯 1)什么是多线程之间通讯 多线程之间通讯,其实就是多个线程在操作同一个资源,但是操作的动作不同. 2)如何通讯 wait().notify().notifyAll()是三个 ...

  4. 多线程之间的通信(等待唤醒机制、Lock 及其它线程的方法)

    一.多线程之间的通信. 就是多个线程在操作同一份数据, 但是操作的方法不同. 如: 对于同一个存储块,其中有两个存储位:name   sex, 现有两个线程,一个向其中存放数据,一个打印其中的数据. ...

  5. java 中多线程之间的通讯之生产者和消费者 (多个线程之间的通讯)

    在真实开发 中关于多线程的通讯的问题用到下边的例子是比较多的 不同的地方时if 和while 的区别 如果只是两个线程之间的通讯,使用if是没有问题的. 但是在多个线程之间就会有问题 /* * 这个例 ...

  6. python处理多线程之间事件通讯方法

    一.什么是事件 每执行一个事情,肯定有该事情的执行后状态,那事件就是该事情发生的信号 在程序中,多线程之间需要通讯,而事件就是方便线程之间的通讯 案例: 1.服务器启动需要5秒 2.客服端启动后去链接 ...

  7. C# 多线程控制 通讯

    一.多线程的概念  Windows是一个多任务的系统,如果你使用的是windows 2000及其以上版本,你可以通过任务管理器查看当前系统运行的程序和进程.什么是进程呢?当一个程序开始运行时,它就是一 ...

  8. C# 多线程控制 通讯 和切换

    一.多线程的概念  Windows是一个多任务的系统,如果你使用的是windows 2000及其以上版本,你可以通过任务管理器查看当前系统运行的程序和进程.什么是进程呢?当一个程序开始运行时,它就是一 ...

  9. “全栈2019”Java多线程第二十七章:Lock获取lock/释放unlock锁

    难度 初级 学习时间 10分钟 适合人群 零基础 开发语言 Java 开发环境 JDK v11 IntelliJ IDEA v2018.3 文章原文链接 "全栈2019"Java多 ...

随机推荐

  1. 卸载重装ngin的问题解决方案

    1,卸载nginx不保留配置文件 $ sudo apt-get --purge remove nginx 2,卸载自动安装且不再需要的依赖包 $ sudo apt-get autoremove 3,卸 ...

  2. javascript判断数组是否包含了指定的元素

    jQuery写法: var arr = [ "xml", "html", "css", "js" ]; $.inArra ...

  3. SpringBoot-属性直接注入

    SpringBoot-属性直接注入 SpringBoot-属性直接注入 上面我们说到,如果公共的属性,我们可以使用Java类加载Properties文件,来达到复用的目的,在SpringBoot中,我 ...

  4. C# Winform使用线程,委托定时更新界面UI控件,解决界面卡顿问题(转载)

    一.定时执行主界面控件值 1.利用定时器 Thread t = null; private void InitTSJK() { t = new Thread(new ThreadStart(GetDa ...

  5. P1083 是否存在相等的差

    P1083 是否存在相等的差 转跳点:

  6. 官网英文版学习——RabbitMQ学习笔记(五)Publish/Subscribe

    发布/订阅模式:把一个消息发送给多个消费者. 前几篇文章的思想是,我们好像看到了生产者将消息直接发送给queue,然后消费者也从queue中进行消费.其实并非如此,RabbitMQ中的消息传递模型的核 ...

  7. Day4-T1

    原题目 Hades 与 Dionysus 在狂饮后玩起了多米诺骨牌的小游戏. 现在桌上有 N 块多米诺骨牌,每块多米诺骨牌上半部分和下半部分上都有一个整数.每次翻转可让 一块多米诺骨牌上下翻转,即上下 ...

  8. 好记性不如烂笔头--shell参数及shell判断if系列

    $0 当前脚本的文件名$n 传递给脚本或函数的参数.n 是一个数字,表示第几个参数.例如,第一个参数是$1,第二个参数是$2$# 传递给脚本或函数的参数个数$* 传递给脚本或函数的所有参数$@ 传递给 ...

  9. HDU_4965 Fast Matrix Calculation 2014多校9 矩阵快速幂+机智的矩阵结合律

    一开始看这个题目以为是个裸的矩阵快速幂的题目, 后来发现会超时,超就超在  M = C^(N*N). 这个操作,而C本身是个N*N的矩阵,N最大为1000. 但是这里有个巧妙的地方就是 C的来源其实 ...

  10. 经验分享:如何搞定Personal Statement?

    最近又到申请季啦,如何自己DIY申请,如何准备文书成为众多留学生关心的问题.不管是你申请本科,硕士,还是博士,相信这篇文章都能帮助到你.下面来说一下文书中一个很重要的组成,就是个人陈述Personal ...