表示一个公共资源,可以被多个线程使用。同一时刻只能被一个线程使用。
在其他线程释放资源之前,当前线程无法继续执行
认为线程之间不会发生冲突,多个线程可以没有障碍的进入临界区。如果检测到数据异常,则回滚自己的操作,确保数据安全(可能导致没有线程离开临界区)
在无障碍的基础上,要求必然有一个线程能够在有限时间内离开临界区(可能导致重试的线程出现饥饿)
在无锁的基础上,要求所有线程都能够在有限时间内离开临界区
为了提高系统速度,需要在增加CPU处理器的同时,提高系统内可并行化的模块比重
如果串行化比例很小,并行化比例很大,则增加CPU处理器就能提高系统的速度
一个操作是不可中断的,不会被其他线程干扰。
(对于32位虚拟机,如果对64位的数据进行操作,则不是原子性的)
当一个线程修改了一个共享变量的值,其他线程立即知道这个修改
(缓存优化、硬件优化、指令重排、编辑器优化可能导致操作不可见)
程序按顺序执行
可以保证串行语义的一致性,但无法保证多线程语义的一致性
可以减少中断流水线的次数
Happen-Before原则
不使用thread.run()方法开启线程,它只会串行执行run()方法。
应该使用thread.start();方法新建线程
public class MyThread{
static class Thread1 extends Thread {
@Override
public void run() {
System.out.println("通过继承的方法创建线程");
}
}
public static void main(String[] args) {
Thread1 thread1 = new Thread1();
thread1.start();
}
}
public static void main(String[] args) {
Thread thread = new Thread(){
@Override
public void run() {
System.out.println("通过匿名内部类的方法创建线程");
}
};
thread.start();
}
public class MyThread{
static class Thread2 implements Runnable{
@Override
public void run() {
System.out.println("通过接口的方法创建线程");
}
}
public static void main(String[] args) {
Thread thread = new Thread(new Thread2());
thread.start();
}
}
通过Thread.sleep(时间),让线程休眠若干时间,如果在休眠中被中断,则会抛出InterruptedException
睡眠中仍然持有资源,无法被其他线程唤醒!
不用使用thread.stop()方法,会直接结束线程,导致数据不一致。
需要自己决定何时让线程结束(状态量)
public class MyThread {
static class Thread1 extends Thread {
//标志结束的信号
private boolean stop;
public void stopMe() {
stop = true;
}
@Override
public void run() {
while (true) {
System.out.println("实现线程");
try {
//让线程慢一点,容易观察
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
//接收到结束信号,停止循环
if (stop) {
System.out.println("结束了");
break;
}
}
}
}
public static void main(String[] args) throws InterruptedException {
Thread1 thread = new Thread1();
thread.start();
// thread.stop();
//等待1秒后,让线程停止
Thread.sleep(1000);
thread.stopMe();
}
}
告诉系统应该退出,由系统决定
设置中断标志位:thread.interrupt(); (类似thread.stopMe();)
检查中断标志位:Thread.currentThread().isInterrupted();(类似判断语句if(stop))
检查中断标志位并清零:Thread.interrupted();
中断方法不仅提醒系统结束,也能处理睡眠或等待的特殊情况
public class MyThread {
static class Thread1 extends Thread {
private boolean stop;
public void stopMe() {
stop = true;
}
@Override
public void run() {
while (true) {
System.out.println("实现线程");
try {
Thread.sleep(100);
} catch (InterruptedException e) {
//抛出异常的同时会清除中断标记
System.out.println("我在睡觉你还中断我?");
//再次设置标记
Thread.currentThread().interrupt();
}
if (Thread.currentThread().isInterrupted()) {
System.out.println("结束了");
break;
}
}
}
}
public static void main(String[] args) throws InterruptedException {
Thread1 thread = new Thread1();
thread.start();
// thread.stop();
Thread.sleep(1000);
// thread.stopMe();
thread.interrupt();
}
}
等待时会释放所持资源,可以被其他线程唤醒!
public class WaitAndNotify {
final static Object object = new Object();
static class ThreadA extends Thread{
private String name;
public ThreadA(String name) {
super(name);
this.name = name;
}
@Override
public void run() {
synchronized (object){
System.out.println(name+"持有了对象");
try {
System.out.println("对象想等待了");
object.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(name+"又持有了对象");
}
}
}
static class ThreadB extends Thread{
@Override
public void run() {
synchronized (object){
System.out.println("B持有了对象");
System.out.println("对象准备好了");
object.notifyAll();
}
}
}
public static void main(String[] args) {
//一个线程等待
// ThreadA a = new ThreadA("A");
// a.start();
// ThreadB b = new ThreadB();
// b.start();
//多个线程等待
ThreadA[] as = new ThreadA[5];
for (int i = 0; i < 5; i++) {
as[i] = new ThreadA("A"+i);
as[i].start();
}
ThreadB b = new ThreadB();
b.start();
}
}
public class SuspendAndResume {
static class ThreadA extends Thread {
private boolean suspend = false;
public void suspendMe() {
System.out.println("挂起线程");
suspend = true;
}
//唤醒线程——通知
public void resumeMe() {
System.out.println("唤醒线程");
suspend = false;
synchronized (this) {
notify();
}
}
@Override
public void run() {
while (true) {
synchronized (this) {
//被挂起了——等待
while (suspend) {
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("线程A开始工作");
}
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
public static void main(String[] args) throws InterruptedException {
ThreadA a = new ThreadA();
a.start();
Thread.sleep(1000);
a.suspendMe();
Thread.sleep(1000);
a.resumeMe();
}
}
通过thread.join(),一个线程需要使用等待依赖的线程thread执行完毕,才能继续执行
public class Join {
static volatile int i = 0;
static class ThreadA extends Thread{
@Override
public void run() {
for (i = 0; i < 10; i++) {
}
}
}
public static void main(String[] args) throws InterruptedException {
ThreadA a = new ThreadA();
a.start();
a.join();
System.out.println(i);
}
}
通过Thread.yield(),当前线程让出CPU,再重新进行争夺。
适合一个低优先级、占用CPU资源多的线程
可以保证数据的可见性和有序性,不能保证原子性
确保操作的原子性,线程之间的有序性和可见性
Java中使用1到10或者3个静态变量表示优先级,一般高优先级在竞争资源时更有优势
thread.setPriority(优先级);
public class DaemonTest {
static class Daemon extends Thread{
@Override
public void run() {
while (true){
System.out.println("我在进行后台工作...");
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
public static void main(String[] args) throws InterruptedException {
Thread thread = new Daemon();
//设置守护线程
thread.setDaemon(true);
thread.start();
//休眠3秒后,主线程结束,所以守护线程也结束了
Thread.sleep(3000);
}
}
如果线程数量多,并且功能明确,则可以把相同功能的线程放置在一个线程组中
public class ThreadGroupTest {
static class Group implements Runnable{
@Override
public void run() {
String group = Thread.currentThread().getThreadGroup().getName();
String name = Thread.currentThread().getName();
while (true){
System.out.println(group+"--"+name);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
public static void main(String[] args) {
ThreadGroup group = new ThreadGroup("Test");
Thread t1 = new Thread(group,new Group(),"Thread1");
Thread t2 = new Thread(group,new Group(),"Thread2");
t1.start();
t2.start();
System.out.println("当前活跃线程:"+group.activeCount());
group.list();
}
}
用Vector代替ArrayList
用ConcurrentHashMap代替HashMap