提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
文章目录
- 一、进程是什么?
- 二、线程是什么?
- 三、线程和进程区别是什么?
- 四、串行,并行,并发的区别
- 五、线程实现的几种方法
- 1.继承Tread
- 2.实现Runnable接口
- 3.通过匿名内部类和Lamda表达式来实现 (也是通过继承类实现和实现)
- 4、实现callable接口
- 5、通过创建线程池的方法来创建线程
- 创建线程的方总结
- 线程的生命周期
- 线程常用方法
- 线程小案例
- 题目一
- 题目二
- 题目三
- 题目四
- 总结
一、进程是什么?
在学习线程之前,我们先来谈谈进程 首先进程是什么 ?
进程是程序相关资源的时候分配的最小单位,每一个进程是独立的都有自己的内存 一个进程室友多个线程组成
二、线程是什么?
线程是cpu分配的最小单元,或者cpu调度时分配的最小单元
线程需要资源更少 可以看做一个轻量级的进程
线程会共享进程的,线程有独立的空间(栈,程序)
线程同信更方便
三、线程和进程区别是什么?
线程是程序执行时分配的最小单元
而进程则是操作系统资分配的最小单位
一个线程会共享进程中的内存 而线程有自己的独立的空间
四、串行,并行,并发的区别
在说他们的区别之前先说说他们是什么
串行:多个指令依次执行,所有的指令一条一条执行的
并发:每一个线程单独一段指令,cpu在线程中进行切换(并不是同时执行)
并行:多个cpu内核同时执行多个线程
总结:在线程中单核 在宏观上是并行 在微观上是串行。而并行由于现在计算机高速发展可以有多核存在 所以可以多个线程同时进行 就是并行的区别
五、线程实现的几种方法
1.继承Tread
1 第一步继承类
2重写run方法
3 通过线程start方法来开启线程
package com.test.demo.entity.test;
// 通过继承Thread类
public class ThreadOne extends Thread {
//重写run()方法
@Override
public void run() {
System.out.println("今天跟金风大人学线程");
}
//main方法执行
public static void main(String[] args) {
//创建线程one
ThreadOne one=new ThreadOne();
//通过start方法
one.start();
}
}
执行效果:
今天跟金风大人学线程
2.实现Runnable接口
主要步骤
1先让一个实体类实现Runnabe接口
2.实现Runnable接口之后就要重写run方法
3创建一个实现Runnable接口的对象传给Thread
4.创建Thread对象 执行 start方法开启线程
package com.test.demo.entity.test;
/**
* 实现Runnable接口
*/
public class ThreadOne implements Runnable {
//主方法
public static void main(String[] args) {
//创建一个实现Rnnable接口对象
ThreadOne one=new ThreadOne();
//将实现Runnable接口对象传给Thread
Thread thread = new Thread(one);
//开启线程
thread.start();
}
//实现run方法
@Override
public void run() {
System.out.println("金风大人教线程");
}
}
执行效果:
今天跟金风大人学线程
3.通过匿名内部类和Lamda表达式来实现 (也是通过继承类实现和实现)
/**
* 用lamda表达式和函数式接口来实现
*/
public class ThreadOne {
public static void main(String[] args) {
//创建一个Thread对象,通过函数式接口来实现
Thread thread = new Thread(()->{
System.out.println("金风大人教线程");
});
thread.start();
//通过匿名内部类进行使用
Thread thread1=new Thread(new Runnable() {
@Override
public void run() {
System.out.println("金风大人教线程");
}
});
thread1.start();
}
}
执行结果
金风大人教线程
金风大人教线程
4、实现callable接口
1.创建一个类实现callable接口对象
2.实现接口里面的方法 call方法体里面写线程要执行代码,可以设置返回值
3.创建一个FutureTask对象 ,用来接收返回值,并且传入参数 是实现这个Callable接口的对象
4.创建一个Thread对象 然后在将FutureTask对象传入进去
5.通过调用FuntureTask对象的get方法来得到返回结果
代码如下(示例):
public class ThreadOne implements Callable {
public static void main(String[] args) throws Exception {
//创建一个实现了Callable接口的实体类
ThreadOne one = new ThreadOne();
//创建FutureTask对象用来接收执行开启线程后的值
FutureTask futureTask = new FutureTask(one);
//创建一个线程将FutureTask的对象传个线程
Thread tread = new Thread(futureTask);
//开启线程
tread.start();
//可以得到线程的值
System.out.println(futureTask.get());
}
//实现Callable接口实现call()方法
@Override
public Object call() throws Exception {
System.out.println("各位看官大人好");
return "金风大人教你们学线程";
}
}
5、通过创建线程池的方法来创建线程
1.创建线程池
2.将一个线程加入到线程池里面去
data = pd.read_csv(
package com.test.demo.entity.test;
import java.util.concurrent.*;
public class ThreadOne {
public static void main(String[] args) throws Exception {
//创建线程池 这个线程池长度不限制
ExecutorService service= Executors.newCachedThreadPool();
//创建线程池 线程池长度设置为5
ExecutorService service1= Executors.newFixedThreadPool(5);
//直接开启线程运行
for (int i=0;i<50;i++){
//放进线程池里面去 通过execute()方法
service.execute(()->{
System.out.println(Thread.currentThread().getName());
});
}
}
}
创建线程的方总结
一共四种方法
第一种直接继承Thread
第二种直接实现Runnable
第三种直接实现Callable接口
第四种 线程池
第一种和第二种没有返回值
它们之间的区别是Thread需要继承 由于Java单继承的缘故
所以会导致继承了Thread之后不能继承其他的类
而实现Runnable 接口就不需要考虑这个问题
一般推荐使用实现Runnable接口
而第三种实现Callable接口的区别124都没有返回值而他有返回值可以通过FuntrueTas的get方法进行实现
第四种用线程池可以将线程重复使用降低了资源消耗 提高响应速度 创建好的线程可重复使用 而且提高了他的可管理性
线程的生命周期
线程一共有五个生命周期
分别是 新建new 就绪状态 Ready Running运行状态 blocked阻塞状态 terminated终止状态
线程常用方法
方法名 | 作用 |
start | 启动线程 |
stop | 停止线程 禁用 可能出现死锁问题 |
getName | 得到线程名 |
setName | 更改线程名 |
sleep(毫秒) | 睡眠,毫秒 |
setPriority | 设置优先级(1到10级) |
setDaemon(true) | 设置后台线程,案例GC |
jion() | 插队 |
线程小案例
题目一
- 设计两个线程,一个线程负责打印1~100以内所有的偶数;然后,另外一个线程负责打印1到100以内所有的奇数。测试时,分别设置线程的优先级,观察执行的顺序
package com.test.demo.entity.homework1;
/**
* 1. 设计两个线程,一个线程负责打印1~100以内所有的偶数;然后,另外一个线程负责打印1~100以内所有的奇数。
*测试时,分别设置线程的优先级,观察执行的顺序
* @金风大人
*/
public class ThreadOne {
public static void main(String[] args) {
Thread thread = new Thread(() -> {
for (int i = 0; i <= 100; i++) {
if (i % 2 == 0) {
System.out.println(Thread.currentThread().getName()+"-->"+i);
}
}
});
Thread thread1 = new Thread(() -> {
for (int i = 0; i <= 100; i++) {
if (i % 2 != 0) {
System.out.println(Thread.currentThread().getName()+"-->"+i);
}
}
});
thread.start();
thread1.start();
thread1.setPriority(10);
}
}
题目二
- 实现一个线程,用于扫描某个目录下的所有文本文件(包括:java、txt、html),并将文字内容打印出来。
package com.test.demo.entity.homework2;
import java.io.*;
public class WorkTwo {
public static void copy(String path){
File file = new File(path);
File[] files = file.listFiles();
for (int i = 0; i < files.length; i++) {
if (!files[i].isDirectory()) {
System.out.println();
try (InputStream inputStream = new FileInputStream(files[i].getAbsolutePath())) {
int length = 0;
byte[] bs = new byte[1024];
while ((length = inputStream.read(bs)) != -1) {
String str = new String(bs, 0, length, "utf-8");
System.out.println(str);
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}else {
copy(files[i].getAbsolutePath());
}
}
}
public static void main(String[] args) {
new Thread(new Runnable() {
@Override
public void run() {
copy("C:\\thread");
}
}).start();
}
}
题目三
3.某人正在看电视连续剧,从第1~88集,看到第10集时,来了一个送快递的,收完快递后后,继续看电视。
package com.test.demo.entity.homework3;
/**
* 某人正在看电视连续剧,从第1~88集,看到第10集时,来了一个送快递的,收完快递后后,继续看电视。
*/
public class ThreadTree {
static Thread thread;
static Thread thread1;
public static void main(String[] args) {
thread = new Thread(() -> {
for (int num = 0; num <= 88; num++) {
System.out.println("邓颖看电视第" + num + "级");
if (num == 20) {
try {
thread1.start();
thread1.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
});
thread1 = new Thread(() -> {
for (int i = 0; i < 10; i++) {
System.out.println("正在送快递");
}
});
thread.start();
}
}
题目四
- 多线程模拟龟兔赛跑:
乌龟和兔子进行1000米赛跑,兔子前进5米,乌龟只能前进1米。
但兔子每20米要休息500毫秒,而乌龟是每100米休息500毫秒。
谁先到终点就结束程序,并显示获胜方
package com.test.demo.entity.homework4;
public class ThreadFour {
static Thread rabbit;
static Thread turtle;
public static void main(String[] args) {
rabbit = new Thread(() -> {
for (int i = 0; i <= 1000; i += 5) {
System.out.println("兔子开始跑步=" + i);
if (i % 20 == 0 && i != 0) {
if (i==1000){
System.out.println("兔子赢");
System.exit(0);
}
try {
rabbit.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
});
turtle = new Thread(() -> {
for (int y = 0; y <= 1000; y += 1) {
System.out.println("乌龟开始跑步=" + y);
if (y % 100 == 0 && y != 0) {
if (y==1000){
System.out.println("乌龟赢了");
System.exit(0);
}
try {
turtle.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
});
rabbit.start();
turtle.start();
}
}
总结
今天金风大人已经讲完了基本的线程知识 对于线程当然这远远不够 我也只是简单的介绍了线程的一些知识 关于后续的线程知识移步到我的个人博客里 关于线程他是cpu调度的基本的最小单位