系列文章目录
提示:这里可以添加系列文章的所有文章的目录,目录需要自己手动添加
例如:第一章 Python 机器学习入门之pandas的使用
提示:写完文章后,目录可以自动生成,如何生成可参考右边的帮助文档
一、线程的概念
线程是CPU资源分配的最小单元
进程包含一个或多个线程
线程需要的资源更少,可以看做是一种轻量级的进程
线程会共享进程中的内存,线程也有独立的空间(栈、程序计数器)
线程互相通信更加方便
二、线程的实现
1.继承Thread类
1.继承Thread类
2.重写run方法
3.调用start启动线程
代码如下(示例):
/**
* 自定义线程类
*/
class MyThread extends Thread{
/**
* 执行指令
*/
public void run() {
for(int i = 0; i < 100; i++){
System.out.println(Thread.currentThread().getName() + "执行了" + i + "次");
}
}
}
public class ThreadDemo {
public static void main(String[] args) {
//创建线程对象
MyThread thread = new MyThread();
//启动线程
thread.start();
}
}
run与start的区别
2.实现Runnable接口
1.实现Runnable接口
2.实现run方法
3.创建实现Runbable接口的对象,传入Thread对象
4.启动线程
代码如下(示例):
/**
* 实现Runnable接口的类
*/
class MyRunnable implements Runnable{
@Override
public void run() {
for (int i = 0; i < 100; i++) {
System.out.println(Thread.currentThread().getName() + "--" + i);
}
}
}
public class RunnableDemo {
public static void main(String[] args) {
//创建Runnable对象,传入Thread对象
MyRunnable myRunnable = new MyRunnable();
Thread thread = new Thread(myRunnable);
thread.start();
//匿名内部类
// Thread thread = new Thread(new Runnable() {
// @Override
// public void run() {
// for (int i = 0; i < 100; i++) {
// System.out.println(Thread.currentThread().getName() + "--" + i);
//
// }
// }
// });
//lambda
// new Thread(() -> {
// for (int i = 0; i < 100; i++) {
// System.out.println(Thread.currentThread().getName() + "--" + i);
// }
// }).start();
}
}
3.实现Callable接口
实现Callable接口可以返回值,继承Thread类和Runnable不行
-
实现Callable接口,实现call方法
-
创建Callable对象,传入FutureTask对象
-
创建FutureTask对象,传入Thread对象
-
启动线程
-
调用get方法得到返回结果
public class CallableDemo {
public static void main(String[] args) {
//创建Callable对象 传入FutureTask对象中
// FutureTask<Long> task = new FutureTask<>(new MyCallable());
FutureTask<Long> task = new FutureTask<>(() -> {
long count = 0;
for (long i = 0; i < 2000000000L; i++) {
count = count + i;
}
return count;
});
//创建FutureTask对象 传入Thread对象中
Thread thread = new Thread(task);
thread.start();
System.out.println("-----等待结果-----");
try {
System.out.println(task.get());
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
}
}
4.使用线程池
三、线程的生命周期
线程的几种状态
- 新建 new
- 准备就绪 start
- 运行 running
- 阻塞 blocking
- 死亡 dead
四、线程小练习
- 设计两个线程,一个线程负责打印1~100以内所有的偶数;然后,另外一个线程负责打印1~100以内所有的奇数。
Thread thread = new Thread(() -> {
for (int i = 1; i <= 100; i+=2) {
System.out.println("奇数为" + i);
}
});
Thread thread2 = new Thread(() -> {
for (int i = 2; i <= 100; i+=2) {
System.out.println("偶数为" + i);
}
});
thread.setPriority(Thread.MAX_PRIORITY);
thread2.setPriority(Thread.MIN_PRIORITY);
thread.start();
thread2.start();
2.实现一个线程,用于扫描某个目录下的所有文本文件(包括:java、txt、html),并将文字内容打印出来。
public static void select(String path){
File file = new File(path);
if (file.isDirectory()) {
File[] files = file.listFiles((dir,name) -> name.endsWith(".java") | name.endsWith(".html") | name.endsWith(".txt") | dir.isDirectory());
if (files != null){
for (File f:files) {
select(f.getPath());
}
}
}else {
try(BufferedReader input = new BufferedReader(new InputStreamReader(new FileInputStream(file),"gbk"))){
String str;
while ((str = input.readLine()) != null){
System.out.println(str);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
public static void main(String[] args) {
Thread thread = new Thread(() -> {
select("D:\\123");
});
thread.start();
}
3.某人正在看电视连续剧,从第1~88集,看到第10集时,来了一个送快递的,收完快递后后,继续看电视。
Thread thread = new Thread(() -> {
for (int i = 1; i <= 88; i++) {
System.out.println("看到第" + i + "集");
if (i == 18){
try {
System.out.println("快递到了");
Thread.sleep(5000);
System.out.println("收完快递,继续看电视");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
});
thread.start();
4.多线程模拟龟兔赛跑:
乌龟和兔子进行1000米赛跑,兔子前进5米,乌龟只能前进1米。
但兔子每20米要休息500毫秒,而乌龟是每100米休息500毫秒。
谁先到终点就结束程序,并显示获胜方
static Thread thread = null;
static Thread thread2 = null;
public static void main(String[] args) {
thread = new Thread(() -> {
for (int i = 0; i <= 1000; i+=5) {
System.out.println("兔子跑了" + i + "米");
if (i == 1000){
System.out.println("兔子赢了");
System.exit(0);
}else if ( i != 0 && i % 20 == 0 ){
try {
System.out.println("兔子休息了");
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
});
thread2 = new Thread(() -> {
for (int i = 0; i <= 1000; i++) {
System.out.println("乌龟跑了" + i + "米");
if (i == 1000){
System.out.println("乌龟赢了");
System.exit(0);
}else if ( i != 0 && i % 100 == 0 ){
try {
System.out.println("乌龟休息了");
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
});
thread.start();
thread2.start();
}
总结
今天学习了线程的概念和使用,了解了程序如何运行,线程的生命周期