多 线 程
1.创建线程的方法
- 1.继承自Thread,重写run方法,
- 2.实现runnable接口,把runnable接口的实例赋值给Thread
import java.util.TreeMap;
/**
* User:yang
*/
class MyTask implements Runnable{
@Override
public void run() {
while (true){
System.out.println("hello");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
public class ThreadDemo2 {
public static void main(String[] args) {
Runnable myTask=new MyTask();
Thread t=new Thread(myTask);
t.start();
}
}
- 3.匿名内部类(thread)
Thread t2=new Thread(){
@Override
public void run() {
long b=0;
for (long i = 0; i <count ; i++) {
b++;
}
}
};
- 4.匿名内部类(runnable)
public static void main(String[] args) {
Thread t=new Thread(new Runnable() {
@Override
public void run() {
System.out.println("hello");
}
});
t.start();
}
- 5.使用lambda表达式创建线程
public static void main(String[] args) {
Thread t=new Thread(()->{
System.out.println("hello");
});
t.start();
}
2.线程属性
- 线程设置名称setName()
/**
* User:yang
*/
public class ThreadDemo3 {
public static void main(String[] args) {
Thread t1=new Thread(){
@Override
public void run() {
while (true){
System.out.println("hello");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
};
t1.setName("t1");
t1.start();
Thread t2=new Thread(){
@Override
public void run() {
while (true){
System.out.println("hello");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
};
t2.setName("t2");
t2.start();
}
}
- 打印各种属性
/**
* User:yang
*/
public class ThreadDemo4 {
public static void main(String[] args) {
Thread t = new Thread(() -> {
Thread.currentThread().setName("1111");
for (int i = 0; i < 10; i++) {
System.out.println(Thread.currentThread().getName() + "正在运行中");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println(Thread.currentThread().getName() + "运行完毕,即将销毁");
});
System.out.println(t.getId());
System.out.println(t.getName());
System.out.println(t.getState());
System.out.println(t.isDaemon());
System.out.println(t.getPriority());
System.out.println(t.isAlive());
System.out.println(t.isInterrupted());
t.start();
System.out.println("线程创建之后");System.out.println(t.getId());
System.out.println(t.getName());
System.out.println(t.getState());
System.out.println(t.isDaemon());
System.out.println(t.getPriority());
System.out.println(t.isAlive());
System.out.println(t.isInterrupted());
}
}
3.Start方法
- 线程对象被创建出来并不意味着线程就开始运行了,需要Start
4.中断一个线程
- 1.通过共享的标记
/**
* User:yang
*/
public class ThreadDemo6 {
static boolean isRunning = true;
public static void main(String[] args) throws InterruptedException {
Thread t = new Thread() {
@Override
public void run() {
while (isRunning) {
System.out.println("hello");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
};
t.start();
Thread.sleep(5 * 1000);
isRunning = false;
}
}
- 2.调用 interrupt()方法
/**
* User:yang
*/
//调用 interrupt()方法终止
public class ThreadDemo7 {
public static void main(String[] args) throws InterruptedException {
Thread t=new Thread(){
@Override
public void run() {
while (!Thread.currentThread().isInterrupted()){
System.out.println("hello");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
break;
}
}
}
};
t.start();
Thread.sleep(5*1000);
System.out.println("线程终止");
t.interrupt();
}
}
5.等待线程机制
- 不是有顺序的开始,而是能确认结束的顺序。
- join 方法
/**
* User:yang
*/
public class ThreadDemo8 {
public static void main(String[] args) throws InterruptedException {
Thread t=new Thread(){
@Override
public void run() {
int i=0;
while (i<5){
System.out.println("jelol");
i++;
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
};t.start();
//执行到join就会阻塞等待,等到t执行完毕,join才会往下执行
Thread.sleep(6000);
System.out.println("即将调用join");
t.join();
System.out.println("t执行完毕");
}
}
6. 获取当前线程引用
/**
* User:yang
*/
public class ThreadDemo9 {
public static void main(String[] args) {
Thread t1 = new Thread() {
@Override
public void run() {
System.out.println(Thread.currentThread().getId());
System.out.println(this.getId());
}
};
t1.start();
Thread t2 = new Thread() {
@Override
public void run() {
System.out.println(Thread.currentThread().getId());
System.out.println(this.getId());
}
};
t2.start();
System.out.println(Thread.currentThread().getId());
}
}
7. 线程休眠
8.线程的状态
-
NEW
-
RUNNABLE
-
BLOCKED
-
WAITING
-
TIMED_WAITING
-
TERMINATED
/**
* User:yang
*/
public class ThreadDemo10 {
public static void main(String[] args) {
Thread t=new Thread(new Runnable() {
@Override
public void run() {
for (int i = 0; i <1000_0000 ; i++) {
}
}
});
System.out.println("before"+t.getState());
t.start();
while (t.isAlive()){
System.out.println("during"+t.getState());
}
System.out.println("end"+t.getState());
}
}
/**
* User:yang
*/
public class ThreadDemo11 {
public static void main(String[] args) throws InterruptedException {
Thread t=new Thread(new Runnable() {
@Override
public void run() {
while (true){
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
});
t.start();
while (true){
System.out.println(" "+t.getState());
Thread.sleep(1000);
}
}
}
9.线程安全
- 不安全的原因:
- 1.抢占式执行。(万恶之源)
- 2.多个线程修改同一个变量
- 3.修改操作不是原子的
- 4.内存可见性(编译器优化)
- 5.指令重排序(编译器优化)
9.1两个线程分别增加5000,实际结果不是10000
/**
* User:yang
*/
class Counter {
public static int count=0;
public static void increase(){
count++;
}
}
public class ThreadDemo12 {
public static void main(String[] args) throws InterruptedException {
Counter counter=new Counter();
Thread t1=new Thread(){
@Override
public void run() {
for (int i = 0; i < 50000; i++) {
counter.increase();
}
}
};
Thread t2=new Thread(){
@Override
public void run() {
for (int i = 0; i < 50000; i++) {
counter.increase();
}
}
};
t1.start();
t2.start();
t1.join();
t2.join();
System.out.println(counter.count);
}
}
10.线程安全的解决办法(synchronize)
10.1synchronize(关键字) 监视器锁(atm取钱)
- 功能:保证操作的原子性,禁止指令重排序,保证内存可见性
10.2修饰一个方法
相当于加了LOCK,UNLOCK
synchronized public void increase(){
count++;
}
10.3修饰一个代码块
public void increase() {
synchronized (this) {
count++;
}
}
Thread t2 = new Thread() {
@Override
public void run() {
for (int i = 0; i < 50000; i++) {
synchronized(counter){
counter.increase();
}
}
}
};
10.4嵌套加锁
- synchronized内部进行了特殊处理,可重入锁。
/**
* User:yang
*/
class Counter {
public static int count = 0;
// public void increase(){
// count++;
//
// }
synchronized void increase() {
count++;
}
// public void increase() {
// synchronized (this) {
// count++;
// }
// }
}
public class ThreadDemo12 {
public static void main(String[] args) throws InterruptedException {
Counter counter = new Counter();
Thread t1 = new Thread() {
@Override
public void run() {
for (int i = 0; i < 50000; i++) {
synchronized (counter) {
counter.increase();
}
}
}
};
Thread t2 = new Thread() {
@Override
public void run() {
for (int i = 0; i < 50000; i++) {
synchronized (counter) {
counter.increase();
}
}
}
};
t1.start();
t2.start();
t1.join();
t2.join();
System.out.println(counter.count);
}
}
11.volatile(比synchronized更轻量)
- 效果:辅助保证线程安全
- 作用:禁止指令重排序,保证内存可见性,但是不保证原子性
- 主要用于读写同一个变量的时候
- 当两个线程都要写的时候,volatile无能为力,要用synchronized
import java.util.Scanner;
/**
* User:yang
*/
public class ThreadDemo13 {
static class Counter{
volatile public int flag=0;
}
public static void main(String[] args) {
Counter counter=new Counter();
Thread t1=new Thread(){
@Override
public void run() {
while (counter.flag==0){
}
System.out.println("线程1 循环结束");
}
};t1.start();
Thread t2=new Thread(){
@Override
public void run() {
Scanner scanner=new Scanner(System.in);
System.out.println("please input an int ");
counter.flag=scanner.nextInt();
}
};t2.start();
}
}
12.wait/notify
- wait,notify都必须在synchronized里面使用
12.1wait
- 1.释放锁
- 2.等待其他线程的通知
- 3.等通知来了之后,重新尝试获取锁
- 必须在synchronized里面使用
12.2notify
- 作用:通知某个线程从wait醒来
- 必须在synchronized里面使用
- 调用notify方法之后,代码不会立即释放锁,而是执行完synchronized之后才释放锁。同时等待的线程们就尝试重新竞争这个锁
/**
* User:yang
*/
//wait notify 用法
public class ThreadDemo15 {
static public Object locker = new Object();
//用来等待的线程
static class WaitTask implements Runnable {
@Override
public void run() {
synchronized (locker) {
while (true) {
System.out.println("wait 开始");
try {
locker.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("wait 结束");
}
}
}
}
//用来通知的线程
static class NotifyTask implements Runnable {
@Override
public void run() {
synchronized (locker) {
System.out.println("notify 开始");
locker.notify();
System.out.println("notify 结束");
}
}
}
public static void main(String[] args) throws InterruptedException {
Thread t1 = new Thread(new WaitTask());
Thread t2 = new Thread(new NotifyTask());
t1.start();
Thread.sleep(3000);
t2.start();
}
}
12.3notifyAll
- 将所有waiting变成就绪,然后只有一个竞争到,竞争失败的就会blocked
13.注意
- 调用wait/notify/加锁synchronized都是针对同一个对象进行
14.JMM
Java Memory Model Java内存模型