1.线程与进程
1.1进程是操作系统资源分配的基本单位,而线程是任务调度和执行的基本单位。
2.1在软件运行时pc在运行内存中开启一块空间称为为进程,在进程中的操作成为线程
2.多线程
2.1 我们程序运行的时候 肯定至少有一个执行单元 就是一个线程 并且我们称之为 main 主线程。
2.2 如果我们希望在开辟其他的线程去执行代码 ,其他的线程就称之为 分线程。
2.3 主线程和分线程一起执行的时候 就有多个执行单元,我们统称为 多线程。
3.多线程的目的
3.1 多线程是为了同步完成多项任务,不是为了提高运行效率,而是为了提高资源使用效率来提高系统的效率
4.java开启多线程的几种方式
4.1 单线程
4.2通过继承thread的实体类进行创建
public class ThreadOne extends Thread {
@Override
public void run() {
for (int i = 0; i < 1000; i++) {
System.out.println("aaa" + i);
}
}
}
方式二
//方式二实现runable接口
public class ThreadCreateTwo implements Runnable {
@Override
public void run() {
for (int i = 0; i < 1000; i++) {
System.out.println("aaa" + i);
}
}
}
方式三
public static void main(String[] args) {
//创建匿名内部类调用
new Thread(new Runnable() {
@Override
public void run() {
for (int i = 0; i < 1000; i++) {
System.out.println("bbb" + i);
}
}
}).start();
for (int i = 0; i < 1000; i++) {
System.out.println("aaa" + i);
}
}
}
方式四
//方式四实现callable接口
public static void main(String[] args) {
FutureTask task = new FutureTask(new Callable() {
@Override
public Object call() throws Exception {
for (int i = 0; i < 1000; i++) {
System.out.println("bbb" + i);
}
return null;
}
}
);
new Thread(task).start();
for (int i = 0; i < 1000; i++) {
System.out.println("aaa" + i);
}
}
(1)Callable规定的方法是call(),而Runnable规定的方法是run().
(2)Callable的任务执行后可返回值,而Runnable的任务是不能返回值的。
(3)call()方法可抛出异常,而run()方法是不能抛出异常的。
(4)运行Callable任务可拿到一个Future对象, Future表示异步计算的结果。
它提供了检查计算是否完成的方法,以等待计算的完成,并检索计算的结果。
通过Future对象可了解任务执行情况,可取消任务的执行,还可获取任务执行的结果。
Callable是类似于Runnable的接口,实现Callable接口的类和实现Runnable的类都是可被其它线程执行的任务。
5.线程函数基本函数
/**
* @author :zzg
* @description:线程函数基本函数
* @date :2022/3/7 15:02
*/
public class JavaTestTwo {
public static void main(String[] args) {
new Thread(new Runnable() {
@Override
public void run() {
//获取线程的id
long id = Thread.currentThread().getId();
//获取线程的name
String name = Thread.currentThread().getName();
System.out.println(id + "========" + name);
}
}).start();
try {
//线程休眠
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
6 线程函之守护线程
6.1 一个线程可能有一个守护线程,也可你没有守护线程,
6.2 当一个线程结束时那么它的守护线程也会结束
例如守护线程
什么是守护线程?
所谓守护线程是指在程序运行的时候在后台提供一种通用服务的线程,比如垃圾回收线程就是一个很称职的守护者,并且这种线程并不属于程序中不可或缺的部分。因 此,当所有的非守护线程结束时,程序也就终止了,同时会杀死进程中的所有守护线程。反过来说,只要任何非守护线程还在运行,程序就不会终止。
守护线程和用户线程的没啥本质的区别:唯一的不同之处就在于虚拟机的离开:如果用户线程已经全部退出运行了,只剩下守护线程存在了,虚拟机也就退出了。 因为没有了被守护者,守护线程也就没有工作可做了,也就没有继续运行程序的必要了。
垃圾回收线程
垃圾: 不再被使用的内存
垃圾回收:清除不被使用的对象 让其锁占据的内存可以被重新分配
垃圾回收的方式: 手动回收 (c语言 xxx .... xxx.free()) 自动回收 (java GC机制 创建一个守护线程 定期清理内存)
垃圾回收算法: gc线程如何判断某个对象是不是垃圾
开启守护线程
public class JavaTextThree {
public static void main(String[] args) {
//创建一个守护线程
Thread thread = new Thread(new Runnable() {
@Override
public void run() {
System.out.println("这是一个守护线程");
}
});
thread.setDaemon(true);
thread.start();
System.out.println(1);
}
}
7.线程优先级
public class JavaFour {
public static void main(String[] args) {
Thread thread1 = new Thread(new Runnable() {
@Override
public void run() {
for (int i = 0; i < 1000; i++) {
System.out.println("线程优先级1----" + i);
}
}
});
Thread thread2 = new Thread(new Runnable() {
@Override
public void run() {
for (int i = 0; i < 1000; i++) {
System.out.println("线程优先级2----" + 2);
}
}
});
//setPriority设置优先级值越大优先级越高
thread1.setPriority(1);
thread2.setPriority(10);
thread1.start();
thread2.start();
}
}
8 多线程中的概念
1.串行与并发
2.并行与并发
9 四种线程池
1缓存线程池
/*
* 不推荐使用
* 线程池不允许使用Executors去创建,而是通过ThreadPoolExecutor的方式,这样的处理方式让写的同学更加明确线程池的运行规则,规避资源耗尽的风险。 说明:Executors返回的线程池对象的弊端如下:
* 1)FixedThreadPool和SingleThreadPool:
* 允许的请求队列长度为Integer.MAX_VALUE,可能会堆积大量的请求,从而导致OOM。
* 2)CachedThreadPool:
* 允许的创建线程数量为Integer.MAX_VALUE,可能会创建大量的线程,从而导致OOM。
*
* 可缓存无界线程池测试
* 当线程池中的线程空闲时间超过60s则会自动回收该线程,核心线程数为0
* 当任务超过线程池的线程数则创建新线程。线程池的大小上限为Integer.MAX_VALUE,
* 可看做是无限大。
*/
ExecutorService pool = Executors.newCachedThreadPool();
for (int i = 0; i < 100; i++) {
pool.execute(new Runnable() {
@Override
public void run() {
System.out.println("创建一个数据连接池" + Thread.currentThread().getName());
}
});
}
}
}
2.定容线程池
//创建定容的数据连接池
ExecutorService pool = newFixedThreadPool(3);
for (int i = 0; i < 100; i++) {
int finalI = i;
pool.execute(new Runnable() {
@Override
public void run() {
System.out.println("共有三个线程池" + finalI + "---" + Thread.currentThread().getName());
}
});
}
3.单一线程池
//单一线程池
ExecutorService pool = newSingleThreadExecutor();
for (int i = 0; i < 30; i++) {
int finalI = i;
pool.execute(new Runnable() {
@Override
public void run() {
System.out.println("共有一个线程池" + finalI + "---" + Thread.currentThread().getName());
}
});
}
int finalI = i;
pool.execute(new Runnable() {
@Override
public void run() {
System.out.println("共有一个线程池" + finalI + "---" + Thread.currentThread().getName());
}
});
}