java多线程知识点汇总(二)多线程实例解析
本实验主要考察多线程对单例模式的操作,和多线程对同一资源的读取,两个知识。实验涉及到三个类:
1)一个pojo类Student,包括set/get方法。
2)一个线程类,设置student的成员变量age和name的值为111和111
3)另一个线程类,设置student的成员变量age和name的值为222和2222
4)main类,for循环200次,分别创建200个线程1和线程2对同一资源访问。(共400个线程)
1.第一种情况:饿汉式单例模式保证多线程操控的是同一对象
//饿汉式单例模式pojo类
public class Student {
private String age = "";
private String name = "Tome";
private static Student student = new Student();//类加载时候创建对象 public String getNameAndAge() {
return name+":"+age;
}
public void setNameAndAge(String name,String age) {
this.name = name;
this.age = age;
} private Student() //构造函数私有化
{
}
public static Student GetInstace() { //方法区函数,静态函数
return student;
}
}
线程2类:
public class MyThread extends Thread {
@Override
public void run() {
// TODO Auto-generated method stub
System.out.println(Student.GetInstace().hashCode());
}
}
测试类,创建并启动400个线程:
public class AppMain implements Runnable{
public static void main(String[] args) {
AppMain appMain = new AppMain();
for(int i =;i<;i++)
{
Thread thread1 = new Thread(appMain);//线程1
MyThread thread2 = new MyThread();//线程2
thread1.start();
thread2.start();
}
}
@Override
public void run() {
// TODO Auto-generated method stub
System.out.println(Student.GetInstace().hashCode());
}
}
结果:

2.第二种情况:共享资源的写方法不设置任何同步,多个线程可以交叉写数据
public String getNameAndAge() {
return name+":"+age;
}
public void setNameAndAge(String name,String age) { //没有设置任何写同步
this.name = name;
this.age = age;
}
俩线程操控类:
public class MyThread extends Thread {
@Override
public void run() {
// TODO Auto-generated method stub
Student.GetInstace().setNameAndAge("", "");//设置name和age值为1
System.out.println(Student.GetInstace().getNameAndAge(););
}
}
线程2
public class AppMain implements Runnable{
public static void main(String[] args) {
AppMain appMain = new AppMain();
for(int i =;i<;i++)
{
Thread thread1 = new Thread(appMain);
MyThread thread2 = new MyThread();
thread1.start();
thread2.start();
}
}
@Override
public void run() {
// TODO Auto-generated method stub
Student.GetInstace().setNameAndAge("", "");//设置name和age为2
System.out.println(Student.GetInstace().getNameAndAge(););
}
}
执行结果:

3.第三种情况:共享资源的写方法设置同步synchronized,保证同一时刻只有一个线程才能执行写,执行完后才释放锁。
public String getNameAndAge() {
return name+":"+age;
}
synchronized public void setNameAndAge(String name,String age) { //写方法设置synchronized了
this.name = name;
this.age = age;
}
测试类添加打印:
public static void main(String[] args) {
AppMain appMain = new AppMain();
for(int i =;i<;i++)
{
Thread thread1 = new Thread(appMain);
MyThread thread2 = new MyThread();
thread1.start();
thread2.start();
System.out.println(Student.GetInstace().getNameAndAge());//添加打印,显示name和age值
}
}
这样就能多个线程按序设置name和set值了。但为什么测试结果依然有脏数据呢?比如111:222这种脏数据呢?
答案:因为没设置单例对象读get方法的锁,这样读方法可以随时获取值,即使set线程还没执行完,因为没有synchronized限制可以随时访问。
4.第四种情况,共享资源的读方法不同步不synchronized,方便随时读取不受锁的限制。但就像之前说的,会读到写线程还没执行完时的数据,造成数据混乱。因为读线程可以随时读,没有锁的限制。
public String getNameAndAge() { //读方法没有做同步synchronized处理,可以随时读取,就可以读出写线程未执行完的中间数据
return name+":"+age;
}
synchronized public void setNameAndAge(String name,String age) {
this.name = name;
this.age = age;
}
操作结果:

5.第五种情况,读方法也设置synchronized,锁的对象也是this。保证写的时候不能读,保证读的时候不能写。即读写用同一个锁。
synchronized public String getNameAndAge() {
return name+":"+age;
}
synchronized public void setNameAndAge(String name,String age) {
this.name = name;
this.age = age;
}
测试结果:

这样数据就全部准确了,但是这样效率很低,因为读写共同设置一个锁。读的时候不能写,写的时候不能读。全部都是按序来访问。
结论:当多线程共同访问同一资源时候,此共享对象的读写方法,要都设置同一个锁,保证写的时候不能读,读的时候不能写,且读写都是按序执行。才能保证数据的准确性。
同时,也说明了,没有设置锁的方法可以随时执行,随时执行,随时可能被cpu调度以至打断线程的执行,以至读到线程执行一半产生的脏数据。
java多线程知识点汇总(二)多线程实例解析的更多相关文章
- Java面试知识点汇总
Java面试知识点汇总 置顶 2019年05月07日 15:36:18 温柔的谢世杰 阅读数 21623 文章标签: 面经java 更多 分类专栏: java 面试 Java面试知识汇总 版权声明 ...
- java基础知识点补充---二维数组
#java基础知识点补充---二维数组 首先定义一个二维数组 int[][] ns={ {1,2,3,4}, {5,6,7,8}, {9,10,11,12}, {13,14,15,16} }; 实现遍 ...
- 2020最常见的200+Java面试题汇总(含答案解析)
前言 2020年快要结束了,很多朋友问题,有没有整理今年的一些面试题,最近抽时间整理了一份Java面试题.或许这份面试题还不足以囊括所有 Java 问题,但有了它,我相信足以应对目前市面上绝大部分的 ...
- Java基础知识点(二)
前言:Java的基础知识点不能间断. 1.Array和ArrayList的区别 关于Array的用法,参看:http://blog.csdn.net/b_11111/article/details/5 ...
- java多线程知识点汇总(一)多线程基础
1.什么叫多线程程序? 答:一个进程至少有一个线程在运行,当一个进程中出现多个线程时,就称这个应用程序是多线程应用程序. java编写的程序都是多线程的,因为最少有俩线程,main主线程和gc线程. ...
- java多线程知识点汇总(四)多线程知识点脉络图
1.多线程安全问题 1)synchronized关键字:如何加锁的问题,选择synchronized方法还是synchnized代码块. 选择哪个锁问题,this对象,还是class对象(针对stat ...
- Windows 多线程知识点汇总
一.什么叫原子性? 答:一个操作不会被分成两个时间片来执行,不会刚执行到一半,由于时间片到了,CPU就跑去执行其他线程了.在多线程环境中对一个变量进行读写时,我们需要有一种方法能够保证对一个值的操作是 ...
- Java 面试知识点汇总
OOP:(Object Oriented Programming )面向对象编程 重用性.灵活性和扩展性 高内聚.低耦合 面向过程编程与面向对象编程的区别:举例,自己做饭吃与去饭馆吃,去饭馆只需要知道 ...
- java小知识点汇总
1.ConcurrentHashMap使用segment来分段和管理锁,segment继承自ReentrantLock,因此ConcurrentHashMap使用ReentrantLock来保证线程安 ...
随机推荐
- MongoDB 3.x 安装配置
目录 (见右侧目录栏导航)- 1. 安装Mongodb - 1.1 使用二进制包安装 - 1.2 运行MongoDB- 2. MongoDB 配置文件详解 - 2.1 说明 - ...
- CSS背景横向平铺BUG,解决方法
给定DIV一个背景图片横向平铺,缩小浏览器,拉动横向滚动条,此时触发此BUG:背景图片平铺不完整 解决办法: 1.把背景图片写在BODY上,此办法局限于没有使用iframe的情况下,所以少用 2.设定 ...
- java图片转byte转string
第一种:原始乱码: public static void main(String[] args) throws IOException { File imgFile = new File(" ...
- git rebase 过程中遇到冲突该怎么解决?
在执行git rebase 过程中经常遇到问题,此时有点慌,一般如何解决呢? 1.先将本地的冲突手动解决 2.执行下面命令 git add . git rebase --contine //继续re ...
- Mysql的刷脏页问题
平时的工作中,不知道你有没有遇到过这样的场景,一条 SQL 语句,正常执行的时候特别快,但是有时也不知道怎么回事,它就会变得特别慢,并且这样的场景很难复现,它不只随机,而且持续时间还很短. 当内存数据 ...
- 前端JS框架系列之requireJS基础学习
1 背景 伴随着项目功能的不断扩充,客户体验的不断完善,实现交互逻辑的JS代码变得越来越多.起初,为了管理JS代码,我们把JS从页面中解放出来独立成文件,接着又把相似的交互代码提取到公共的JS页面中. ...
- js求区间随机数
function rnd(n, m){ var random = Math.round(Math.random()*(m-n)+n); return random; }
- LoadRunner监控Linux的三种方法
方法一.LR + SiteScope/nmon 方法二.使用rstatd包 1.下载rpc.rstatd-4.0.1.tar.gz 2.解压缩 tar -zxvf rpc.rstatd-4.0.1.t ...
- linux 重写rm命令
重写rm命令 replease rm to trash 必须使用root编辑/etc/bashrc vim /etc/bashrc 在最后面增加如下脚本 saferm () { if [ ! -d ...
- Xcode_7_GM_seed.dmg下载
Xcode_7_GM_seed.dmg下载 Xcode_7_GM_seed.dmg 免费下载链接: http://pan.baidu.com/s/1pJ7oGAZ 密码: y5bx