总结
本文从基础到高级再到实战,由浅入深,把MySQL讲的清清楚楚,明明白白,这应该是我目前为止看到过最好的有关MySQL的学习笔记了,我相信如果你把这份笔记认真看完后,无论是工作中碰到的问题还是被面试官问到的问题都能迎刃而解!
MySQL50道高频面试题整理:
public static void main(String[] args) {
// 匿名内部类
Thread thread = new Thread(new Runnable() {
@Override
public void run() {
// 业务代码
Thread t = Thread.currentThread();
System.out.println("执行任务:" + t.getName());
}
});
// 启动线程
thread.start();
}
}
运行结果:
![](https://img-blog.csdnimg.cn/04cd46e9b2d34195975cd63ed6a42cee.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5r6E55m95piT,size_20,color_FFFFFF,t_70,g_se,x_16)
### 3.2.2 变种方法 2:匿名方式创建子对象
public class ThreadDemo7 {
public static void main(String[] args) {
// 创建线程并初始化
Thread thread = new Thread() {
@Override
public void run() {
Thread t = Thread.currentThread();
System.out.println("任务执行:" + t.getName());
}
};
// 开启线程
thread.start();
}
}
运行结果:
![](https://img-blog.csdnimg.cn/f25ba3833fb24ad086a4841061c3f8ad.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5r6E55m95piT,size_20,color_FFFFFF,t_70,g_se,x_16)
### 3.2.3 变种方法 3:使用 Lambda 匿名 Runnable 方式 (支持 JDK 1.8+ 版本,推荐使用)
public class ThreadDemo6 {
public static void main(String[] args) {
// 创建线程
Thread thread = new Thread(() -> {
// 具体业务
Thread t = Thread.currentThread();
System.out.println("任务执行:" + t.getName());
});
// 执行线程
thread.start();
}
}
运行结果:
![](https://img-blog.csdnimg.cn/01651b5d028640dc938bcb603cc18508.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5r6E55m95piT,size_20,color_FFFFFF,t_70,g_se,x_16)
3.3 创建方式3:带返回值的 Callable
------------------------
public class ThreadDemo8 {
public static void main(String[] args) throws ExecutionException, InterruptedException {
// 创建 Callable 实例
MyCallable myCallable = new MyCallable();
// 用于接收 Callable 结果的对象
FutureTask<Integer> futureTask = new FutureTask<>(myCallable);
// 创建新线程
Thread thread = new Thread(futureTask);
// 启动线程
thread.start();
// 接收新线程执行的结果
int result = futureTask.get();
System.out.println(Thread.currentThread().getName() + "新线程返回的结果为:" + result);
}
private static class MyCallable implements Callable<Integer> {
@Override
public Integer call() {
// 生成随机数0~9
int randomNum = new Random().nextInt(10);
System.out.println(Thread.currentThread().getName() + "随机数" + randomNum);
return randomNum;
}
}
}
运行结果:
![](https://img-blog.csdnimg.cn/5b83ab240ab34cd38ef0777baf9d194b.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5r6E55m95piT,size_20,color_FFFFFF,t_70,g_se,x_16)
**也可通过匿名 Callable 实现:**
public class ThreadDemo9 {
public static void main(String[] args) throws ExecutionException, InterruptedException {
// FutureTask 用于获取线程的执行结果
FutureTask<String> futureTask = new FutureTask<>(new Callable<String>() {
@Override
public String call() throws Exception {
// 新线程执行的任务代码
String[] strings = new String[]{"Java", "MySQL", "Python"};
// 随机返回一个字符串
String result = strings[new Random().nextInt(3)];
System.out.println(Thread.currentThread().getName() + "字符串:" + result);
return result;
}
});
// 创建新线程
Thread thread = new Thread(futureTask);
// 启动线程
thread.start();
String result = futureTask.get();
System.out.println(Thread.currentThread().getName() + "新线程的返回值:" + result);
}
}
运行结果:
![](https://img-blog.csdnimg.cn/b1cd1d496dd340dda6ca17ad99cd23ea.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5r6E55m95piT,size_20,color_FFFFFF,t_70,g_se,x_16)
3.4 小结
-------
创建线程有 3 大类实现方式、7 种实现方法,如果是 JDK 1.8 以上版本,**在不需要获得线程执行结果的情况下,推荐使用 Lambda 方式来创建线程**,因为它的写法足够简洁;**如果想要获取线程执行结果,可使用 FutureTask + Callable 的方式来实现**。
4\. 线程常见构造方法
============
![](https://img-blog.csdnimg.cn/06f171476ed748179454d1c771329c9d.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5r6E55m95piT,size_20,color_FFFFFF,t_70,g_se,x_16)
**具体使用:**
Thread t1 = new Thread();
Thread t2 = new Thread(new MyRunnable());
Thread t3 = new Thread(“这是我的名字”);
Thread t4 = new Thread(new MyRunnable(), “这是我的名字”);
**线程分组的使用:**
public class ThreadDemo12 {
public static void main(String[] args) {
// 创建一个线程分组(百米赛跑)
ThreadGroup threadGroup = new ThreadGroup("thread-group");
// 定义一个公共的线程任务
Runnable runTask = new Runnable() {
@Override
public void run() {
// 生成一个1-3的随机数
int randomNum = (1 + new Random().nextInt(3));
// 跑了n秒后到达终点
try {
Thread.sleep(1000 * randomNum);
} catch (InterruptedException e) {
e.printStackTrace();
}
// 得到执行此线程的方法
Thread thread = Thread.currentThread();
System.out.println(thread.getName() + "选手到达终点:" + randomNum + "s");
}
};
// 线程(运动员)
Thread t1 = new Thread(threadGroup, runTask);
Thread t2 = new Thread(threadGroup, runTask);
Thread t3 = new Thread(threadGroup, runTask);
// 启动线程(开跑)
t1.start();
t2.start();
t3.start();
// 所有人到达终点后宣布成绩
while (threadGroup.activeCount() > 0) {
}
System.out.println("宣布比赛成绩");
}
}
5\. 线程常用属性
==========
![](https://img-blog.csdnimg.cn/0684ee0ae6cc4489910625aea1d9a35e.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5r6E55m95piT,size_20,color_FFFFFF,t_70,g_se,x_16)
===============================================================================================================================================================================================
* ID 是线程的唯⼀标识,不同线程不会重复。
* 名称 是各种调试⼯具用到。
* 状态 表示线程当前所处的⼀个情况。
* 优先级 高的线程理论上来说更容易被调度到。
* 关于守护线程(后台线程),需要记住⼀点:**JVM会在⼀个进程的所有非后台线程结束后,才会结束运行。**
* 是否存活,即简单的理解为 run 方法是否运行结束了。
* 线程的中断问题,下面我们进⼀步说明。
5.1 优先级
-------
> 优先级是 int 类型值,线程优先级1-10,**最小优先级是1,最大优先级是10,默认优先级是5**。
![](https://img-blog.csdnimg.cn/dae0542d960b4d8c93e136be32638e0b.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5r6E55m95piT,size_20,color_FFFFFF,t_70,g_se,x_16)
示例代码:
public class ThreadDemoByPriority2 {
private final static int MAX_COUNT = 1000;
public static void main(String[] args) {
Thread t1 = new Thread(() -> {
Thread t = Thread.currentThread();
int priority = t.getPriority();
for (int i = 0; i < MAX_COUNT; i++) {
System.out.println(t.getName() + "线程优先级:" + priority);
}
}, "线程1");
// 设置线程优先级(10)
t1.setPriority(Thread.MAX_PRIORITY);
Thread t2 = new Thread(() -> {
Thread t = Thread.currentThread();
int priority = t.getPriority();
for (int i = 0; i < MAX_COUNT; i++) {
System.out.println(t.getName() + "线程优先级:" + priority);
}
}, "线程2");
// 设置线程优先级(5)
t2.setPriority(Thread.NORM_PRIORITY);
Thread t3 = new Thread(() -> {
Thread t = Thread.currentThread();
int priority = t.getPriority();
for (int i = 0; i < MAX_COUNT; i++) {
System.out.println(t.getName() + "线程优先级:" + priority);
}
}, "线程3");
// 设置线程优先级(1)
t3.setPriority(Thread.MIN_PRIORITY);
// 同时启动线程
t3.start();
t2.start();
t1.start();
}
}
运行结果:
![](https://img-blog.csdnimg.cn/8a42bbed539f4b5b8e64eb4c6d217e93.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5r6E55m95piT,size_20,color_FFFFFF,t_70,g_se,x_16)
**结论 :**同时启动多个线程,多个线程设置了不同的优先级,并不是一定是优先级高的执行完了再执行优先级低的,而是优先级高的线程获取到CPU时间片的概率更大,更容易被调度到。
5.2 守护线程
--------
### 5.2.1 线程中的分类:
* **用户线程**:主线程main默认是用户线程。
* **守护线程(后台线程**):为用户线程服务的,用户线程全部结束之后,守护线程会跟随结束。
### 5.2.2 守护线程应用
JVM 中的垃圾回收器就是典型的守护线程,程序运行的时候它也运行,当满足条件是进行垃圾回收,当所有线程执行完任务终止时它也会随着退出。
守护线程示例:
public class ThreadDemoByDaemon {
public static void main(String[] args) throws InterruptedException {
// 得到当前的线程
Thread thread = Thread.currentThread();
System.out.println(thread.getName() + "是否是守护线程:" + thread.isDaemon());
Thread t1 = new Thread(() -> {
Thread thread1 = Thread.currentThread();
System.out.println(thread1.getName() + "是否是守护线程:" + thread1.isDaemon());
// 创建子线程
Thread tt1 = new Thread(() -> {
Thread thread2 = Thread.currentThread();
System.out.println(thread2.getName() + "是否是守护线程:" + thread2.isDaemon());
}, "子线程的子线程");
tt1.start();
}, "子线程");
// 手动设置为守护线程
t1.setDaemon(true);
// 启动线程
t1.start();
Thread.sleep(1000);
}
}
执行结果:
![](https://img-blog.csdnimg.cn/e81a397c98034a7488c510816514ec62.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5r6E55m95piT,size_20,color_FFFFFF,t_70,g_se,x_16)
**结论** :
* main线程默认是非守护线程(用户线程)。
* 在默认情况下,在用户线程中创建的子线程也是用户线程。
* 在守护线程中创建的子线程也是守护线程。
**注意** : 线程的类型不能在线程启动后再进行设置,会发生报错。
### 5.2.3 用户线程 VS 守护线程
/**
* 守护线程
*/
private static void daemonThread() {
Thread thread = new Thread(() -> {
for (int i = 0; i < 10; i++) {
System.out.println("守护线程执行:" + i);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
// 设置为守护线程
thread.setDaemon(true);
thread.start();
}
运行结果:
![](https://img-blog.csdnimg.cn/edea0206321f493fa5e5bef010f5fdfd.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5r6E55m95piT,size_20,color_FFFFFF,t_70,g_se,x_16)
/**
* 用户线程
*/
private static void userThread() {
Thread thread = new Thread(() -> {
for (int i = 0; i < 10; i++) {
System.out.println("用户线程执行:" + i);
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
thread.start();
}
运行结果:
![](https://img-blog.csdnimg.cn/492c698d48d04da58ce2bb445e588767.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5r6E55m95piT,size_20,color_FFFFFF,t_70,g_se,x_16)
**结论** :
* JVM 会等待所有用户线程执行完之后再退出。
* JVM 不会等待所有守护线程执行完之后再退出。
### 5.3 是否存活
public class ThreadDemoByAlive {
public static void main(String[] args) {
Thread thread = new Thread(() -> {
for (int i = 0; i < 10; i++) {
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("1.线程执行完了");
});
thread.start();
while (thread.isAlive()) {
}
最后
还有Java核心知识点+全套架构师学习资料和视频+一线大厂面试宝典+面试简历模板可以领取+阿里美团网易腾讯小米爱奇艺快手哔哩哔哩面试题+Spring源码合集+Java架构实战电子书+2021年最新大厂面试题。
static void main(String[] args) {
Thread thread = new Thread(() -> {
for (int i = 0; i < 10; i++) {
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("1.线程执行完了");
});
thread.start();
while (thread.isAlive()) {
}
最后
还有Java核心知识点+全套架构师学习资料和视频+一线大厂面试宝典+面试简历模板可以领取+阿里美团网易腾讯小米爱奇艺快手哔哩哔哩面试题+Spring源码合集+Java架构实战电子书+2021年最新大厂面试题。
[外链图片转存中…(img-wBWNvWut-1714858966687)]