volatile 修饰元素,保证可见性,不保证原子性。
++a 不是原子操作。
给++a加锁
创建原子类,每次自增1
List和Vector
public class SyDemoA1 {
volatile List<String> list = new ArrayList<>();
Vector<String> vec = new Vector<>();
int sum = 0;
AtomicInteger nn = new AtomicInteger(0);
public static void main(String[] args) {
var t = new SyDemoA1();
var t1 = new Thread(t::add, "T1");
var t2 = new Thread(t::add, "T2");
var t3 = new Thread(t::add, "T3");
t1.start();
t2.start();
t3.start();
try {
TimeUnit.SECONDS.sleep(2);
} catch (Exception e) {
e.printStackTrace();
}
System.out.println(t.list.size());
System.out.println(t.vec.size());
System.out.println(t.sum);
System.out.println(t.nn.get());
}
void add() {
String t = Thread.currentThread().getName();
for (int i = 0; i < 10000; i++) {
synchronized (this) {
sum++;
}
nn.incrementAndGet();
list.add("Item-" + t + "-" + i);
vec.add("Item-" + t + "-" + i);
}
System.out.println(t + "结束");
}
}
显示锁的使用,需要手动上锁和解锁
public class ReentrantDemo {
ReentrantLock lock = new ReentrantLock();
public static void main(String[] args) {
ReentrantDemo rd = new ReentrantDemo();
var t1 = new Thread(rd::m, "T1");
var t2 = new Thread(rd::m, "T2");
t1.start();
t2.start();
}
void m() {
String t = Thread.currentThread().getName();
System.out.println(t + "线程运行");
for (int i = 0; i < 10; i++) {
lock.lock();
try {
Thread.sleep(1000);
} catch (Exception e) {
e.printStackTrace();
} finally {
lock.unlock();
}
System.out.println(t + ":" + i);
}
}
死锁模拟
public class ThreadA2 {
Object a = new Object();
Object b = new Object();
public static void main(String[] args) {
ThreadA2 t = new ThreadA2();
var t1 = new Thread(t::m1, "T1");
var t2 = new Thread(t::m2, "T2");
t1.start();
t2.start();
}
void m1() {
String t = Thread.currentThread().getName();
System.out.println(t + "线程运行");
synchronized (a) {
try {
Thread.sleep(1000);
} catch (Exception e) {
e.printStackTrace();
}
synchronized (b) {
}
}
System.out.println("线程结束");
}
void m2() {
String t = Thread.currentThread().getName();
System.out.println(t + "线程运行");
synchronized (b) {
try {
Thread.sleep(1000);
} catch (Exception e) {
e.printStackTrace();
}
synchronized (a) {
}
}
System.out.println("线程结束");
}
}
线程监控,10个一打印
public class MonitorDemoA1 {
CountDownLatch latch = new CountDownLatch(1);
Vector<Integer> vector = new Vector<>();
Random rand = new Random();
public static void main(String[] args) {
MonitorDemoA1 t = new MonitorDemoA1();
var t1 = new Thread(t::adda1, "add");
boolean a = false;
boolean finalbool1 = false;
Callable<Boolean> call = () -> {
return t.counta1(finalbool1);
};
FutureTask<Boolean> ft = new FutureTask<>(call);
var c = new Thread(ft, "count");
t1.start();
c.start();
try {
a = ft.get();
} catch (Exception e) {
e.printStackTrace();
}
if (a) {
t1.interrupt();
}
}
void adda1() {
String tn = Thread.currentThread().getName();
System.out.println(tn + "线程启动");
while (true) {
try {
Thread.sleep(500);
} catch (Exception e) {
//e.printStackTrace();
System.out.println("线程退出");
break;
}
System.out.println("已经添加一个元素");
vector.add(rand.nextInt(1, 101));
if (vector.size() == 10) {
latch.countDown();
}
}
}
boolean counta1(boolean a) {
String tn = Thread.currentThread().getName();
System.out.println(tn + "监控线程启动");
try {
latch.await();
System.out.println("容器已到10个");
a = true;
} catch (Exception e) {
e.printStackTrace();
}
return a;
}
}
方法二:不好,但也能用
public class MonitorDemoA2 {
static AtomicInteger nn = new AtomicInteger(0);
Object o = new Object();
public static void main(String[] args) {
MonitorDemoA2 t = new MonitorDemoA2();
var t1 = new Thread(t::adda1, "add");
var t2 = new Thread(t::counta1, "count");
t1.start();
//t2.setDaemon(true);
t2.start();
}
void adda1() {
String tn = Thread.currentThread().getName();
System.out.println(tn + "线程启动");
while (true) {
try {
Thread.sleep(500);
} catch (Exception e) {
e.printStackTrace();
}
nn.incrementAndGet();
System.out.println("执行一次" + nn.get());
}
}
void counta1() {
String tn = Thread.currentThread().getName();
System.out.println(tn + "监控线程启动");
while (true) {
if (nn.get() % 10 == 0) {
System.out.println("容器已到10个");
}
try {
Thread.sleep(400);
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
注意时间,待修改
门闩类的使用
public class ThreadA1 {
static List<Integer> list = new ArrayList<>();
static CountDownLatch latch = new CountDownLatch(2);
Random rand = new Random();
public static void main(String[] args) {
ThreadA1 t = new ThreadA1();
var t1 = new Thread(t::adda1, "T1");
var t2 = new Thread(t::adda1, "T2");
t1.start();
t2.start();
try {
latch.await();
} catch (Exception e) {
e.printStackTrace();
}
System.out.println(list);
}
void adda1() {
String t = Thread.currentThread().getName();
for (int i = 0; i < 10; i++) {
int a = rand.nextInt(0, 101);
list.add(a);
System.out.println(t + "线程添加了" + a);
}
latch.countDown();
}
}
wait() sleep() notifyAll()
在锁中:
wait()等待时会释放锁,里面不填写时间时会进入阻塞状态,只有等待notify()和notifyAll()唤醒,一般notify()只唤醒一个,而notifyAll()会唤醒所有wait()的线程。
sleep() notifyAll()时不会释放锁。
interrupt()打断
打断 执行指令时会产生异常,打断线程。
public static void main(String[] args) {
var t = new Thread(() -> {
String tn = Thread.currentThread().getName();
while (true) {
try {
Thread.sleep(1000);
System.out.println(tn + "已经休眠1秒");
} catch (Exception e) {
//e.printStackTrace();
break;
}
}
}, "T1");
t.start();
try {
Thread.sleep(4000);
} catch (Exception e) {
e.printStackTrace();
}
System.out.println("中断线程");
t.interrupt();
}