这里将自己学习java及其应用的一些笔记、积累分享一下,如果涉及到了文章、文字侵权,请联系我删除或调整。
一、多线程
1.1 多线程数据访问冲突
在实际的开发过程中,对于一个简单业务,单线程就能很好的解决问题。然而,现实情况是我们往往需要多线程去完成一个业务逻辑,而多线程的并行操作就会带来一些问题,例如多线程的数据访问冲突。
多线程的数据访问冲突:
- 多个线程,共享访问数据,在不加任何保护措施的情况下,易产生脏数据
- 一个线程访问到修改的一半的数据,称为脏数据
1.2 练习:多线程数据访问冲突
package 线程;
import java.util.Arrays;
// 进程1与进程2同时访问与修改数组c,造成冲突
public class Test_多线程数据访问冲突 {
// 配置初始数据
static char[] c = { '-', '-', '-', '-' };
static char v = '*';
public static void main(String[] args) {
// 修改数组c
new Thread() {
@Override
public void run() {
while(true) {
for(int i = 0;i<c.length;i++) {
c[i] = v;// 更新数组中的值为v
}
v = (v=='-' ? '*':'-');// 利用三木运算符每轮更新v的值
}
};
}.start();
// 读取数组c
new Thread() {
@Override
public void run() {
while(true) {
System.out.println(Arrays.toString(c));
}
};
}.start();
}
}
二、线程同步
2.1 线程同步(synchronized)概述
- 所谓同步是指:多个线程,步调一致地执行
- 让多个线程,争夺同一个对象的“同步锁” ,谁抢到谁执行,抢不到要等待
- 同步锁:任何对象,都有唯一的一个同步锁
- synchronized,java中的关键字
遇到同步关键字,要先抢到锁才能执行
抢不到就要等待
2.2 synchronized用法
- 对象锁,即争夺指定对象的锁
synchronized(对象) {
}
-
方法锁,即抢当前对象(this)的锁
synchronized void f() {
}
- 抢“类”的锁(静态是属于类的)
static synchronized void f() {
}
2.3 练习:synchronized实现对象锁
package 线程;
import java.util.Arrays;
// 进程1与进程2同时访问与修改数组c,造成冲突
public class Test_线程同步_多线程数据访问冲突 {
// 配置初始数据
static char[] c = { '-', '-', '-', '-' };
static char v = '*';
public static void main(String[] args) {
// 修改数组c
new Thread() {
@Override
public void run() {
while (true) {
// 添加同步锁,解决访问冲突
synchronized (c) {
for (int i = 0; i < c.length; i++) {
c[i] = v;// 更新数组中的值为v
}
v = (v == '-' ? '*' : '-');// 利用三木运算符每轮更新v的值
}
}
}
}.start();
// 读取数组c
new Thread() {
@Override
public void run() {
// 添加同步锁,解决访问冲突
synchronized (c) {
while (true) {
System.out.println(Arrays.toString(c));
}
}
};
}.start();
}
}
2.4 练习:synchronized实现方法锁、类锁
package 线程;
public class Test_synchronized方法与synchronized类 {
public static void main(String[] args) {
R1 r1 = new R1();
R1 r2 = new R1();
Thread t1 = new Thread(r1);
Thread t2 = new Thread(r2);
// t1线程启动后,执行r1.run(),即add()
t1.start();
// main线程中死循环检查i是否是奇数
while(true) {
int i = r2.get();
if(i%2==1) {
System.out.println("i是奇数:"+i);
System.exit(0);// 关闭虚拟机
}else {
System.out.println("i是偶数!"+i);
}
}
}
static class R1 implements Runnable{
static int i;
@Override
public void run() {
while(true) {
add();
}
}
// 当利用同一个对象r1进行访问与修改时,方法的同步可以保证不冲突,
// 但由于i是静态变量,则当出现r2对象时,仍会出现冲突
public static synchronized void add() {
i++;
i++;
}
public static synchronized int get() {
return i;
}
}
}