JAVA学习笔记(四十三)- ThreadLocal

死锁

/*
 * 死锁:多个线程使用不同的锁,每个线程都需要另一个线程持有的锁
 * 出现:同步的嵌套
 *
 */
public class Test01 {
    public static void main(String[] args) {
        Tom tom = new Tom();
        Alice alice = new Alice();
        MyThread mt1 = new MyThread(tom, alice, true);
        MyThread mt2 = new MyThread(tom, alice, false);
        Thread th1 = new Thread(mt1);
        Thread th2 = new Thread(mt2);
        th1.start();
        th2.start();
    }
}

class MyThread implements Runnable {
    private Tom tom;
    private Alice alice;
    boolean flag;

    public MyThread(Tom tom, Alice alice, boolean flag) {
        this.tom = tom;
        this.alice = alice;
        this.flag = flag;
    }

    @Override
    public void run() {
        if (flag) {
            synchronized (tom) { // tom鎖
                tom.say();
                try {
                    Thread.sleep(10);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                synchronized (alice) { // alice鎖
                    tom.show();
                }
            }
        } else {
            synchronized (alice) { // alice鎖
                alice.say();
                try {
                    Thread.sleep(10);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                synchronized (tom) {// tom鎖
                    alice.show();
                }
            }
        }
    }

}

/*
 * tom需要笔
 */
class Tom {
    public void say() {
        System.out.println("给我笔");
    }

    public void show() {
        System.out.println("得到笔");
    }
}

/*
 * alice需要笔
 */
class Alice {
    public void say() {
        System.out.println("给我本子");
    }

    public void show() {
        System.out.println("得到本子");
    }
}

ThreadLocal

import java.util.Random;

/*
 * ThreadLocal
 * 为每个线程提供一个变量的副本,不同的线程获取的变量不同
 * 线程局部变量的含义,即产生的变量为某个线程所有,对此线程是局部的
 */
public class Test03 {
    public static void main(String[] args) {
        MyThread3 mt=new MyThread3();
        Thread th1=new Thread(mt, "线程一");
        Thread th2=new Thread(mt, "线程二");
        Thread th3=new Thread(mt, "线程三");
        Thread th4=new Thread(mt, "线程四");

        th1.start();
        th2.start();
        th3.start();
        th4.start();
    }
}

class MyThread3 implements Runnable {
    //创建一个线程局部变量,用于管理多线程要操作的对象
    private static ThreadLocal<Student> local=new ThreadLocal<Student>();

    //获取线程局部变量的方法
    public Student getStudent(){
        //第一次获取时,获取的值必须为空
        Student stu = local.get();
        if(stu==null){
            stu=new Student();//第一次获取对象时没有学生,所以需要手动创建一个对象
            local.set(stu);//将学生对象交由ThreadLocal管理
        }
        return stu;
    }

    @Override
    public void run() {
        Random r = new Random();
        int age = r.nextInt(100);
        //从ThreadLocal中获取本线程的学生对象
        Student stu=getStudent();
        stu.setAge(age);
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(Thread.currentThread().getName() + "***"
                + stu.getAge());

    }

}

synchronized和ThreadLocal区别

import java.util.Random;

/*
 * synchronized和ThreadLocal区别
 * synchronized用于线程间的数据共享,而ThreadLocal则用于线程间的数据隔离
 */
public class Test02 {
    public static void main(String[] args) {
        Student stu=new Student();
        MyThread2 mt=new MyThread2(stu);
        Thread th1=new Thread(mt, "线程一");
        Thread th2=new Thread(mt, "线程二");
        th1.start();
        th2.start();
    }
}

class MyThread2 implements Runnable {
    private Student stu;

    public MyThread2(Student stu) {
        this.stu = stu;
    }

    @Override
    public void run() {
        while(true){
        Random r = new Random();
        int age = r.nextInt(100);
        synchronized (stu) {
            stu.setAge(age);
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName() + "***"
                    + stu.getAge());
        }
    }
    }

}

/*
 * 学生类
 */
class Student {
    private int age;

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }
}
时间: 2024-08-12 21:11:46

JAVA学习笔记(四十三)- ThreadLocal的相关文章

【Unity 3D】学习笔记四十三:布料

布料 布料是特殊的组件,它可以变化成任意形状,比如说:随风飘的旗子,窗帘等 创建布料的方法有两种:创建布料对象,在游戏对象中添加布料组件.前者通过hierarchy视图中选择create--cloth即可,创建后,系统会自动将互动布料组件(interactive clothe)与布料渲染组件(cloth renderer)添加值该对象中.后者是在导航菜单中选component--physics--interactive cloth菜单项即可. 交互布料组件是由网格组成的布料,只要用于布料的逻辑判

java学习笔记四:static的几个角落及小谈多态

最近有点事情,没有及时更新笔记,学习不可弃,总结一下最近的学习,其中重点是static的一些应用,多态是一种设计理念,了解较容易,想如火纯清的确不是一件容易的事情. 对于static,主要有两点是我所学习的. 1.首先简单的介绍一下static的定义.static是静态的意思,就是说这个类变量或者类方法不需要实例化就可以使用.使用static的变量是类变量,也成为静态域(static field).这些是static的基本语义,了解了这些,继续向下看. java核心技术(卷一)对于静态有这样一段

Java学习笔记四(代码块 )

1 代码块的分类:java中的代码块是指使用{}括起来的一段代码,根据位置不同可以分为四种: 普通代码块 构造快 静态代码块 同步代码块 今天主要学习前三种代码块,同步代码块在学习到多线程部分的时候再加学习. 2 普通代码块:直接定义在方法中的代码块,如下: public class CodeSpace { public static void main(String args[]){ { int x = 30; System.out.println("普通代码块x="+x); } /

JAVA学习笔记(四十七)- 事件监听

定义ActionListener接口的实现类实现事件监听 import java.awt.Button; import java.awt.Frame; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.WindowEvent; import java.awt.event.WindowListener; /* * 事件监听 */ public class Te

JAVA学习笔记(四十九)- Swing相关组件

JFrame组件 import java.awt.Color; import javax.swing.JFrame; import javax.swing.JPanel; /* * Swing是在AWT基础上的扩展 * javax.swing包及其扩展包,组件的命名多以J开关 * * JFrame组件 */ public class Test08 { public static void main(String[] args) { JFrame frame=new JFrame("我的窗体&qu

Java学习笔记—第十三章 数据库编程入门

第十三章 数据库编程入门 了解JDBC Java中对数据库的访问主要是通过JDBC进行的.JDBC是Java数据库连接技术(Java Database Connectivity)的简称,是用于执行SQL语句的API,可以为多种关系数据库提供统一访问.由一组用Java语言编写的类和接口组成.(SQL是Structure Query Language的缩写,意义为结构化查询语言,是一种标准的关系数据库访问语言.) JDBC的工作机制 使用JDBC完成对数据库的访问主要包括以下五个层次:Java应用程

Java学习笔记四——运算符

算术运算符 加减乘除(+.-.*./)就不说了. 求余运算符% 描述:第一个操作数除以第二个操作数,得到一个整除的结果后剩下的值就是余数 注意:求余预算的结果不一定总是整数,当操作数是浮点数时,结果可能是小数. double a = 5.2; double b = 3.1; double mod = a%b; System.out.println(mod);//值为2.1 自增运算符++ 自增运算符++有两个要点: ++是单目运算符只能操作一个操作数 ++只能操作在数值型(整数.浮点型)的变量上

Java学习笔记四:static关键字

1.static表示什么? static表示"全局"或者"静态"的意思.在Java中没有全局变量的概念,static 可以简单的理解为全局的,独立的一个功能. (1)当我们在使用 static 修饰成员变量或者成员方法的时候,通常会在Java内存中为这些变量或者方法指定了一块独立的区域(这块区域可能在栈中,也有可能在堆中). (2)如果静态的变量或方法在不出其作用域的情况下,其 引用句柄是不会发生改变的. (3)这块区域是内存共享的,它的引用都指向同一个位置,就是说

JAVA学习笔记(四十八)- 适配器类 Adapter

适配器类 Adapter,对接口中的抽象方法进行空实现 import java.awt.Button; import java.awt.Frame; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import java.awt.event.MouseListener; import java.awt.event.WindowAdapter; import java.awt.event.WindowEve