进程(process):运行的程序
线程(thread):是操作系统能够进行运算调度的最小单位
两者关系:
一个进程可以包含多个线程,
进程包含main线程,gc线程。(mian线程是程序的入口,用于执行整个程序)
Thread 类(单继承有局限性)
//1.继承Thread类
public class Testthread1 extends Thread{
@Override
public void run() {
//2.重写run方法
for (int i = 0; i < 20; i++) {
System.out.println("run"+i);
}
}
public static void main(String[] args) {
//3.创建一个线程对象
Testthread1 t1 = new Testthread1();
//4.调用start()方法
t1.start();
for (int i = 0; i < 20; i++) {
System.out.println("main"+i);
}
}
}
Runnable接口(推荐使用)
//1.实现Runnable接口
public class Testthread2 implements Runnable{
@Override
public void run() {
//2.重写run方法
for (int i = 0; i < 20; i++) {
System.out.println("run"+i);
}
}
public static void main(String[] args) {
//3.创建一个线程对象
Testthread2 t1 = new Testthread2();
//4.丢入Runnable接口实现类并调用start()方法
new Thread(t1).start();
for (int i = 0; i < 20; i++) {
System.out.println("main"+i);
}
}
}
Callable接口(了解)
注意:线程开启后不一定立即执行,什么时候开启由cpu决定。
好处:
new Company(new You()).Wedding();
new Thread(()-> System.out.println("开心")).start();
public class Lambda {
public static void main(String[] args) {
Lmd lmd = () -> {
System.out.println("I love you.");
};
lmd.Like();
}
}
interface Lmd{
public void Like();
}
使用Lamda的好处
函数式接口:一个接口只包含唯一一个抽象方法。
用Lamda表达式来实现函数式接口。
总结:
? 观测线程状态:
thread.getState();
创建状态 NEW
Thread t = new Thread();
就绪状态
t.start();//执行完立即进入就绪状态
运行状态 RUNNABLE
cpu调度后,开始真正执行线程体的代码块
阻塞状态 BLOCKED
sleep、wait、或者同步锁
死亡状态 TERMINATED
线程中断或者结束
线程停止:
//设立标志位,利用标志位使线程停止
private Boolean flag = true;
public void stop(){
this.flag = false;
}
public void run() {
int i = 0;
while(flag) {
//content
}
}
线程休眠(sleep):
//模拟网络延时
//倒计时
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
Date startT = new Date(System.currentTimeMillis());//获取系统当前时间
System.out.println(new SimpleDateFormat("HH:mm:ss").format(startT));//输出当前系统时间
线程礼让(yield):
//让当前正在执行的线程暂停,但不阻塞
//将线程从运行状态转为就绪状态
//让cpu重新调度,礼让不一定成功,看cpu心情
Thread.yield();
线程强制执行(join):
//Join合并线程,待此线程执行完成后,再执行其他线程
for (int i = 0; i < 200; i++) {
if (i == 100){
thread.join();//i=100时,thread会霸占资源,等thread执行完了才会让出资源 //从而继续执行主线程
}
System.out.println("main"+i);
}
线程优先级(priority):
//优先级默认 1-10
//优先级高不一定就先执行,但其被执行的概率很高
Thread.setPriority(6); //设置优先级
Thread.currentThread().getPriority(); //获取优先级
守护线程(daemon):
//守护线程等用户线程结束后会自动结束
//设置守护线程
Thread.setDaemon(true); //默认是false表示是用户线程
线程同步 = 队列 + 锁
synchronized
//锁的对象是变化的量,需要增删改的对象
public synchronized void function(){
}
synchronized(obj){
}
//JUC安全类型的集合
CopyOnWriteArrayList
lock
//定义lock锁
private final ReentrantLock lock = new ReentrantLock();
try{
lock.lock();
//代码块
}finally {
lock.unlock();
}
//对比lock和synchronized
1.lock是显示锁、synchronized是隐式锁
2.lock只有代码块锁,synchronized有代码块锁和方法锁
//多个线程相互抱着对方需要的资源,然后形成僵持
经常创建和销毁,使用量特别大的资源,比如并发情况下的线程,对性能影响很大
解决思路:提前创建好多个线程,放入线程池中,使用时直接获取,使用完放回池中。
好处:
//1.创建服务,创建线程池
ExecutorService service = Executors.newFixedThreadPool(10);
//2.执行
service.execute(new MyThread());//MyThread实现了Runnable
//3.关闭连接
service.shutdown();
---------------------------------------------------------------
//创建执行服务
ExecutorService ser = Executors.newFixedThreadPool(3);
//提交执行
Future<Boolean> r1 = ser.submit(t1);//t1 是Callable对象
Future<Boolean> r2 = ser.submit(t2);
Future<Boolean> r3 = ser.submit(t3);
//获取结果
boolean rs1 = r1.get();
boolean rs2 = r2.get();
boolean rs3 = r3.get();
//关闭连接
ser.shutdownNow();
原文:https://www.cnblogs.com/lk0528/p/13978964.html