创建线程的三种方式:
- 继承Thread:
private class TestThread extends Thread{
@Override
public void run() {
super.run();
}
}
//启动
TestThread testThread = new TestThread();
testThread.start();
- 实现Runnable接口
private class TestThread1 implements Runnable{
@Override
public void run() {
}
}}
//启动
Thread testThread1 = new Thread(new TestThread1());
testThread1.start();
- Callable及FutureTask,获取多线程返回值
private class TestThread2 implements Callable{
@Override
public String call() throws Exception {
//运行逻辑,并返回结果
return "a"+"b";
}
}
//启动
Callable testThread2 = new TestThread2();
FutureTask futureTask = new FutureTask<>(testThread2);
Thread thread = new Thread(futureTask);
thread.start();
Thread的常用方法
方法 | 说明 |
---|---|
start() | 启动线程 |
setName(String name) | 设置线程名称 |
setPriority(int priority) | 设置线程优先级,默认5,取值1-10,优先级系统之后尽量优先调用并不是优先级高的一定先执行; |
join(long millisec) | 抢占线程,使用后该线程执行完毕前其他线程不等待;传入时间(毫秒)占用多长时间后其他线程继续可以执行; |
interrupt() | 终止线程 |
isAlive() | 测试线程是否处于活动状态 |
Thread静态(static)方法
方法 | 说明 |
---|---|
yield() | 暂停当前正在执行的线程对象,并执行其他线程。 |
sleep(long millisec)/sleep(long millis, int nanos) | 挂起线程xx秒,参数不可省略 |
currentThread() | 返回对当前正在执行的线程对象的引用 |
holdsLock(Object x) | 当前线程是否拥有锁 |
sleep()和wait()的区别
本质的区别是:sleep不释放锁,wait释放锁;
用法上的不同:sleep(milliseconds)可以用时间指定来使他自动醒过来,
如果时间不到只能调用interreput()来终止线程;
wait()可以用notify()/notifyAll()直接唤起。
线程的生命周期状态
线程的状态可以使用getState()查看
状态 | 描述 |
---|---|
NEW | 尚未启动 |
RUNNABLE | 正在执行中 |
BLOCKED | 阻塞的(被同步锁或者IO锁阻塞) |
WAITING | 永久等待状态 |
TIMED_WAITING | 等待指定的时间重新被唤醒的状态 |
TERMINATED | 执行完成 |
synchronized关键字(线程同步)
synchronized关键字提供了一种锁机制,能确保共享变量的互斥访问,防止数据不一致的问题出现。
- 修饰一个代码块,被修饰的代码块称为同步语句块,其作用的范围是大括号{}括起来的代码,作用的对象是调用这个代码块的对象;
- 修饰一个方法,被修饰的方法称为同步方法,其作用的范围是整个方法,作用的对象是调用这个方法的对象;
- 修改一个静态的方法,其作用的范围是整个静态方法,作用的对象是这个类的所有对象;
- 修改一个类,其作用的范围是synchronized后面括号括起来的部分,作用主的对象是这个类的所有对象。
修饰一个代码块
一个线程访问一个对象中的synchronized(this)同步代码块时,其他试图访问该对象的线程将被阻塞;
public static void main(String[] args) {
MyThread myThread = new MyThread();
//注意引用同一个对象,不要new 2次
Thread one = new Thread(myThread, "one");
Thread two = new Thread(myThread, "two");
one.start();
two.start();
}
private static int count=0;
public static class MyThread implements Runnable{
@Override
public void run() {
synchronized (this){
for (int i = 0; i <5 ; i++) {
count=count+1;
System.out.print(Thread.currentThread().getName()+"-"+count+",");
try {//方便查看执行顺序
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
//执行结果:
one-1,one-2,one-3,one-4,one-5,two-6,two-7,two-8,two-9,two-10,
修饰一个方法
//调用
for (int i = 0; i <5 ; i++) {
TestThread bank = new TestThread();
bank.start();
}
private int count=0;
private class TestThread extends Thread{
@Override
public void run() {
super.run();
System.out.println("value="+getValue());
try {
Thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
private synchronized int getValue(){
count=count+1;
return count;
}
}
//输出结果:value=1,value=2,value=3,value=4,value=5
指定要给某个对象加锁 (修饰的对象如果是static则加锁的是整个类)
//调用
for (int i = 0; i <10 ; i++) {
Bank bank = new Bank();
if (i%2==0){
bank.setName("A");
}else {
bank.setName("B");
}
bank.start();
}
private Object balance=100;
private class Bank extends Thread{
@Override
public void run() {
super.run();
synchronized (balance){
if (getName().equals("A")){
Integer balance1= (Integer) balance;
balance=balance1+50;
System.out.println("存钱:"+balance);
}else {
Integer balance1= (Integer) balance;
balance=balance1-50;
System.out.println("取钱:"+balance);
}
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
//输出:存钱:150,取钱:100,取钱:50,取钱:0,取钱:-50,取钱:-100,存钱:-50,存钱:0,存钱:50,存钱:100
线程协作 wait()、notify/notifyAll() 详解
- wait()、notify/notifyAll() 方法是Object的本地final方法,无法被重写。
- wait()使当前线程阻塞,前提是 必须先获得锁,一般配合synchronized 关键字使用,即,一般在synchronized 同步代码块里使用 wait()、notify/notifyAll() 方法。
- 由于 wait()、notify/notifyAll() 在synchronized 代码块执行,说明当前线程一定是获取了锁的;
- wait() 需要被try catch包围,以便发生异常中断也可以使wait等待的线程唤醒。
- notify 和wait 的顺序不能错,如果A线程先执行notify方法,B线程在执行wait方法,那么B线程是无法被唤醒的。
//调用 2个子线程顺序执行,一个执行一次;
Product product = new Product();
new addProduct(product).start();
new subProduct(product).start();
//生产商品
private class addProduct extends Thread {
private Product product;
public addProduct(Product product) {
this.product = product;
}
@Override
public void run() {
super.run();
while (true) {
product.addProduct();
}
}
}
//消费商品
private class subProduct extends Thread {
private Product product;
public subProduct(Product product) {
this.product = product;
}
@Override
public void run() {
super.run();
while (true) {
product.subProduct();
}
}
}
//商品类
private class Product {
private int product = 0;
private boolean isAdded = false;//通过参数控制协作
public synchronized void addProduct() {
if (isAdded) {
try {
wait();//线程等待
} catch (InterruptedException e) {
e.printStackTrace();
}
}
product = product + 1;
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("add-" + product);
isAdded=true;
notifyAll();//唤醒所有等待线程
}
public synchronized void subProduct() {
if (!isAdded) {
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
product = product - 1;
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("sub-" + product);
isAdded=false;
notifyAll();
}
}
//输出结果
add-1
sub-0
add-1
sub-0
add-1
sub-0
add-1
...