线程
线程分为用户线程和守护线程
线程创建的方法
public class ThreadTest01 extends Thread {
@Override
public void run() {
for (int i = 0; i < 5; i++) {
System.out.println(Thread.currentThread().getName()+"--"+i);
}
}
public static void main(String[] args) {
ThreadTest01 t1 = new ThreadTest01();
ThreadTest01 t2 = new ThreadTest01();
ThreadTest01 t3 = new ThreadTest01();
t1.start();
t2.start();
t3.start();
}
}
运行截图
public class ThreadTest01 implements Runnable {
@Override
public void run() {
for (int i = 0; i < 5; i++) {
System.out.println(Thread.currentThread().getName()+"--"+i);
}
}
public static void main(String[] args) {
ThreadTest01 t1 = new ThreadTest01();
ThreadTest01 t2 = new ThreadTest01();
ThreadTest01 t3 = new ThreadTest01();
(new Thread(t1)).start();
(new Thread(t2)).start();
(new Thread(t2)).start();
}
}
import org.apache.commons.io.FileUtils;
import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.util.concurrent.*;
public class TCallable implements Callable<Boolean> {
private String url;
private String file;
@Override
public Boolean call() {
downloader d = new downloader(url,file);
return true;
}
TCallable(String url,String file){
this.url = url;
this.file = file;
}
public static void main(String[] args) throws ExecutionException, InterruptedException {
TCallable t1 = new TCallable("http://blog.wlwjwamp.com/Upload/thumb/dst/thumb_20201018025636068981.png","1.png");
TCallable t2 = new TCallable("http://blog.wlwjwamp.com/Upload/thumb/dst/thumb_20201018025636068981.png","2.png");
TCallable t3 = new TCallable("http://blog.wlwjwamp.com/Upload/thumb/dst/thumb_20201018025636068981.png","3.png");
/*******************************核心****************************************/
//创建执行服务
ExecutorService esr = Executors.newFixedThreadPool(3);
//提交执行
Future<Boolean> r1 = esr.submit(t1);
Future<Boolean> r2 = esr.submit(t2);
Future<Boolean> r3 = esr.submit(t3);
//获取结果
boolean res1 = r1.get();
boolean res2 = r2.get();
boolean res3 = r3.get();
//关闭服务
esr.shutdown();
/*******************************核心****************************************/
}
}
class downloader{
public downloader(String url,String File){
try {
FileUtils.copyURLToFile(new URL(url),new File(File));
System.out.println("下载成功:"+File);
} catch (IOException e) {
e.printStackTrace();
}
}
}
Lambda表达式
函数式接口(Functional Interface)就是一个有且仅有一个抽象方法,但是可以有多个非抽象方法的接口。
是函数式接口,则可以使用Lambda表达式简化
(params)->表达式
(params)->{语句}
线程状态
线程可以处于以下状态之一:
-
NEW (new) 尚未启动的线程处于此状态。
-
RUNNABLE (runnable) 在Java虚拟机中执行的线程处于此状态。
-
BLOCKED (blocked) 被阻塞等待监视器锁定的线程处于此状态。
-
WAITING (waiting) 正在等待另一个线程执行特定动作的线程处于此状态。
-
TIMED_WAITING (timed_waiting) 正在等待另一个线程执行动作达到指定等待时间的线程处于此状态。
-
TERMINATED (terminated) 已退出的线程处于此状态。
方法
void join() 等待这个线程死亡。
boolean isAlive() 测试这个线程是否活着。
Thread.State getState() 返回此线程的状态。
static void sleep(long millis) 睡觉
static void yield() 对调度程序的一个暗示,即当前线程愿意产生当前使用的处理器。
线程优先级
void setPriority(int newPriority) 更改此线程的优先级。
int getPriority() 返回此线程的优先级。
线程的优先级为:1~10
public final static int MIN_PRIORITY = 1;
/**
* The default priority that is assigned to a thread.
*/
public final static int NORM_PRIORITY = 5;
/**
* The maximum priority that a thread can have.
*/
public final static int MAX_PRIORITY = 10;
daemon守护线程
并发:同一个对象或多个线程同时操作
public synchronized void method (param){}
synchronized方法控制对“对象”的访问,每个对象对应一把锁,每个synchronized方法都必须获得调用该方法的对象的锁才能执行,否则线程会堵塞,方法一旦执行,就会独占该锁,直到该方法结束才会释放锁,后面被堵塞的线程才可以获取这个锁
synchronized(Obj){} 同步块
synchronized方法锁的是this 本次对象
synchronized(obj){}块锁的是传入的对象
一般锁的对象应该是 :并发的访问,且需要修改的对象
死锁
死锁是这样一种情形:多个线程同时被阻塞,它们中的一个或者全部都在等待某个资源被释放。由于线程被无限期地阻塞,因此程序不可能正常终止。
java 死锁产生的四个必要条件:
- 1、互斥使用,即当资源被一个线程使用(占有)时,别的线程不能使用
- 2、不可抢占,资源请求者不能强制从资源占有者手中夺取资源,资源只能由资源占有者主动释放。
- 3、请求和保持,即当资源请求者在请求其他的资源的同时保持对原有资源的占有。
- 4、循环等待,即存在一个等待队列:P1占有P2的资源,P2占有P3的资源,P3占有P1的资源。这样就形成了一个等待环路
就是我锁住你需要的资源,你锁住我需要的资源,一直僵持
lock
可重入锁 ReentrantLock
lock.lock() 和 lock.unlock()
import java.util.concurrent.locks.ReentrantLock;
public class TestLock implements Runnable {
private int tickNum = 10;
private boolean flag = true;
private final ReentrantLock lock = new ReentrantLock();
@Override
public void run() {
while (flag){
try{
lock.lock();
if (tickNum > 0){
try {
Thread.sleep(300);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(tickNum--);
}else{
break;
}
}finally {
lock.unlock();
}
}
}
public static void main(String[] args) {
TestLock t1 = new TestLock();
(new Thread(t1)).start();
(new Thread(t1)).start();
(new Thread(t1)).start();
}
}
线程通信
void wait() 导致当前线程等待,直到另一个线程调用该对象的 notify()方法或 notifyAll()方法。
void wait(long timeout) 导致当前线程等待,直到另一个线程调用 notify()方法或该对象的 notifyAll()方法,或者指定的时间已过。
void notify() 唤醒正在等待对象监视器的单个线程。
void notifyAll() 唤醒正在等待对象监视器的所有线程。
均是Object类中的方法,只能在同步方法和同步代码块中使用,否则会抛出异常
线程池
Runnable使用的是submit,而Callable 是Future r1 = esr.submit(t1);
因为Callable有返回值,而Runnable没有
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class TestPool implements Runnable {
@Override
public void run() {
for (int i = 0; i < 3; i++) {
System.out.println(Thread.currentThread().getName()+"--"+i);
}
}
public static void main(String[] args) {
ExecutorService esr = Executors.newFixedThreadPool(3);
esr.submit(new TestPool());
esr.submit(new TestPool());
esr.submit(new TestPool());
esr.shutdown();
}
}