文档章节

java 多线程中需要注意的几点

一不留神
 一不留神
发布于 2017/02/16 15:50
字数 890
阅读 104
收藏 0

1.对象的线程安全与非安全的理解

比如:ArrayList与Vector

线程安全:是指多线程同时操作一个对象的时候的时候是安全的Vector是线程安全的

线程非安全:首先非安全不是不安全,只是如果多线程同时操作对象的时候就会有问题,会出数据丢失,抛出异常等。ArrayList是线程非安全

2.多线程共享的int类型变量自减或者自增操作也是非安全的,boolean类型的设置true或者false也是线程非安全的

我们往往会对多条数学运算进行线程安全控制比如下面的代码

synchronized(Test.class){
   num = num +1;
   num = num -10;
}

如果是++或--,我们往往会忘记加同步

如果是单条计算加synchronized,volatile或者使用对应的安全操作类型AtomicInteger,此时使用volatile或者是AtomicInteger最简单

如果涉及多次运算 那就必须控制整个代码块了,使用synchronized 或者lock

线程安全的类型操作:

int -->AtomicInteger

booelan -->AtomicBoolean

long -->AtomicLong

3.多线程使用synchronized的时候,注意锁对象,否则就可能出现加锁了也无法保证同步。

方法加synchronized:锁的是当前this对象,也就是具体的某个实例。也就是说当多线程同时调用该实例的方法的时候synchronized才起作用保证同步。如果每个线程都新建一个实例,那么这个synchronized是不起作用的。

public class Test {
	public static void main(String[] args) {
		for (int i = 0; i < 1000; i++) {
			new MyThread(new MyTest()).start();
		}
	}
}
class MyThread extends Thread{
	private MyTest test;
	public MyThread(MyTest test) {
		super();
		this.test = test;
	}

	@Override
	public void run() {
		test.test();
	}
}
class MyTest {
	public synchronized void test(){
		System.out.println("0");
		try {
			Thread.sleep(1000);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		System.out.println("1");
	}
}

上面的例子希望打印的结果是0 1 0 1 0 1

而如果用上面的写法new MyThread(new MyTest()).start();,打印的结果是 0  0  0  0  1   1   1...

这是因为方法test加的锁,锁的是当前的实例对象

 

而如果将上面的代码修改:

MyTest test = new MyTest();
        for (int i = 0; i < 1000; i++) {
            new MyThread(test).start();
        }

打印的结果符合预期: 0  1  0  1

注意:不是说第二种写法就最好,而是说两种方式解决的问题不一样,要具体问题具体分析,使用哪种方式的前提是:多线程共享的对象是谁,锁的对象是谁,如果多线程没有共享该对象(可能一个线程一个对象)此时还需不需要进行同步控制。

举例:

在spring框架中,service的一个方法需要同步,那么最简单的方式就是方法上加synchronized。因为spring的全局service一般都是一个实例,多线程共享的对象就是service,此时方法上加synchronized,就相当于在这个service实例上加锁,当然可以达到多线程同步控制了。

在struts中的action中,如果有一个逻辑需要控制访问次数,那么这时候,就需要用同步块,并且锁的对象一定要是整个项目唯一的(一般class对象),这是因为struts的action一般都是原型的,一次调用会产生一个新的实例,这时候如果方法上加synchronized就不起作用了, 必须要锁一个全局唯一的一个对象。

4.如果要使用线程,最好使用线程池来控制

不用使用new Thread()来创建

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

© 著作权归作者所有

一不留神
粉丝 8
博文 31
码字总数 23780
作品 0
郑州
后端工程师
私信 提问
JDK基础--ThreadLocal原理分析与使用场景

ThreadLocal原理分析与使用场景 一、什么是ThreadLocal变量 ThreadLoal 变量,线程局部变量,同一个 ThreadLocal 所包含的对象,在不同的 Thread 中有不同的副本。这里有几点需要注意: 因为...

spinachgit
04/09
17
0
Java 基础语法(一) 类、方法、实例变量的概念

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_35619188/article/details/85004955 类、方法、实例变量的概念 对象:对象是类的一个实例,有状态和行为。...

三棵面包树
2018/12/14
0
0
SimpleDateFormat 不是线程安全的,请小心使用

SimpleDateFormat 是 Java 中一个非常常用的类用来对日期字符串进行解析和格式化输出,但如果使用不小心会导致非常微妙和难以调试的问题,因为 DateFormat 和 SimpleDateFormat 类不都是线程...

红薯
2012/03/26
5.4K
12
Java多线程学习(五)线程间通信知识点补充

系列文章传送门: Java多线程学习(一)Java多线程入门 Java多线程学习(二)synchronized关键字(1) java多线程学习(二)synchronized关键字(2) Java多线程学习(三)volatile关键字 Ja...

一只蜗牛呀
2018/04/16
0
0
java多线程系列:通过对战游戏学习CyclicBarrier

CyclicBarrier是java.util.concurrent包下面的一个工具类,字面意思是可循环使用(Cyclic)的屏障(Barrier),通过它可以实现让一组线程到达一个屏障(也可以叫同步点)时被阻塞,直到最后一...

huangzd
2018/01/06
0
0

没有更多内容

加载失败,请刷新页面

加载更多

Rust:最小化窗口后 CPU占用率高 (winit,glutin,imgui-rust)

最近试着用 imgui-rust 绘制界面,发现窗口最小化后CPU占用会增大。 查询的资料如下: https://github.com/rust-windowing/winit/issues/783 https://github.com/ocornut/imgui/issues/1151 ...

reter
27分钟前
8
0
cloud-zuul路由网关

九、zuul路由网关 概述 1.1 能干嘛 路由、过滤 路由基本配置 路由访问映射规则 十、springCloud config分布式配置中心

榴莲黑芝麻糊
27分钟前
12
0
Circuit Breaker模式

Circuit Breaker模式会处理一些需要一定时间来重连远程服务和远端资源的错误。该模式可以提高一个应用的稳定性和弹性。 问题 在类似于云的分布式环境中,当一个应用需要执行一些访问远程资源...

mskk
40分钟前
16
0
写论文之前的准备都有哪些?干货来了!

原文链接:https://www.lwfdy.com/archives/144.html 之前跟大家谈了许多有关于初稿修改以及写作事项需要注意的问题,那么今天我们来说一说,在写之前,我们需要做哪些准备呢,为了做到下笔如...

辅导员
46分钟前
11
0
idea快捷键

Alt + Enter 引入类 Ctrl + O 查看我们继承的类或者接口中的方法,以及我们要实现的方法 Ctrl + Alt + b 查看接口实现类中方法(就是我们使用接口编程时,在调用实现类方法处直接Ctrl+鼠标左...

行者终成事
54分钟前
13
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部