- 一、线程的概念
- 二、串行,并行,并发
- 三、线程的实现
- 1. 继承Thread
- 2.实现Runnable接口
- 3.实现Callable接口
- Thread,Runnable,Callable创建线程的区别
- 三、线程的生命周期
- 五.线程常用方法
- 练习
- 总结
一、线程的概念
1.程序和进程
程序:程序是一种静态概念,磁盘上的一系列文件组成一个程序
进程:进程是一种动态概念,是运行中的程序,一个程序有一个或多个进程
2.进程和线程的区别
进程是程序执行是相关资源分配的最小单位,进程之间是相互独立互不干扰的,一个进程包含一个或多个线程
线程是CPU分配的最小单位,线程之间共享进程的内存,线程有自己独立的空间
二、串行,并行,并发
串行:多个指令一个一个的执行 并发:每个线程单独运行,CPU在这些线程中切换执行,线程并不是一起执行的 并行:多个CPU内核执行多个线程,实现多个线程同时执行三、线程的实现
线程的实现有四种方式: 1.继承Thread类 2.实现Runnable接口 3.实现Callable接口 4.使用线程池1. 继承Thread
1.继承Thread类,重写run方法,调用starts方法
class MyThread extends Thread{
@Override
public void run() {
for (int i = 0; i < 1000; i++) {
System.out.println(Thread.currentThread().getName()+"启动"+i+"次");
}
}
}
public class ThreadTest {
public static void main(String[] args) throws InterruptedException {
MyThread myThread1=new MyThread();
myThread1.start();
for (int i = 0; i < 1000; i++) {
System.out.println(Thread.currentThread().getName()+"启动"+i+"次");
}
}
}
2.实现Runnable接口
1.实现Runnable接口,实现run方法,创建实现Runnable接口的对象,创建Thread对象传入实现Runnable接口的对象 调用start方法
class MyRunnable implements Runnable{
@Override
public void run() {
for (int i = 0; i < 1000; i++) {
System.out.println(Thread.currentThread().getName()+"--"+i);
}
}
}
public class RunnableTest {
public static void main(String[] args) {
//实现Runnable接口,方法一
MyRunnable myRunnable=new MyRunnable();
//实现Runnable接口,方法二,匿名内部类
Thread thread=new Thread(myRunnable);
Thread thread1=new Thread(new Runnable() {
@Override
public void run() {
for (int i = 0; i < 1000; i++) {
System.out.println(Thread.currentThread().getName()+"--"+i);
}
}
});
//实现Runnable接口,方法三,lamda表达式
Thread thread2=new Thread(()->{
for (int i = 0; i < 1000; i++) {
System.out.println(Thread.currentThread().getName()+"--"+i);
}
});
thread.start();
thread1.start();
thread2.start();
for (int i = 0; i < 1000; i++) {
System.out.println(Thread.currentThread().getName()+"--"+i);
}
}
}
3.实现Callable接口
1.实现Callable接口,实现call方法,创建实现Callable接口的对象,创建FutrueTask对象传入实现Callable接口的对象,创建Thread对象传入FutrueTask对象,调用start方法
class MyCallable implements CallableThread,Runnable,Callable创建线程的区别{ @Override public Long call() throws Exception { long sum=0; for (int i = 0; i < 1000000; i++) { sum+=i; } return sum; } } public class CallableTest { public static void main(String[] args) throws ExecutionException, InterruptedException { FutureTask futureTask=new FutureTask(new MyCallable()); Thread thread=new Thread(futureTask); thread.start(); System.out.println("执行结果"); System.out.println(futureTask.get()); } }
1.Thread创建线程是继承,因为java是单继承,会导致继承Thread的类不能继承别的类
2.Runnable和Callable是实现接口,java可以多实现
3.在实现Runnable,和Callable接口时,必须实现run方法和Call方法,不容易出错
4.Callable有返回值,可以通过get()方法获取返回值,Runnable和Thread是没有返回值的
| 方法 | 使用 |
|---|---|
| start() | 启动线程 |
| stop | 停止线程,紧张使用,可能会导致线程死锁等问题 |
| getName | 获得线程名称 |
| setName | 设置线程名称 |
| sleep | 线程休眠 |
| setPriorty | 设置线程的优先级(1-10)等级越高,抢占CPU的几率更大 |
| setDaemon | 设置为后台线程,TRUE,守护其他线程,为其他线程服务,如 GC(垃圾回收)如果没有其他线程,后台线程也会关闭 |
| Join | 线程的加入(合并)插队 |
package com.tx.work;
public class WorkOne {
static Thread t1;
static Thread t2;
public static void main(String[] args) {
t1= new Thread(new Runnable() {
public void run() {
for (int i=1;i<=100;i++){
if (i%2==0){
System.out.println("偶数:"+i);
}
}
}
});
t2= new Thread(new Runnable() {
public void run() {
for (int i=1;i<=100;i++){
if (i%2==1){
System.out.println("奇数:"+i);
}
}
}
});
t1.setPriority(Thread.MIN_PRIORITY);
t2.setPriority(Thread.MAX_PRIORITY);
t1.start();
t2.start();
}
}
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("D:\work");
}
}).start();
}
}
public class WorkThree {
static Thread thread1;
static Thread thread;
public static void main(String[] args) {
thread=new Thread(()->{
for (int i = 1; i <= 88; i++) {
System.out.println("看电视"+i);
if (i==10){
thread1.start();
try {
thread1.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
});
thread1=new Thread(()->{
System.out.println("送快递");
});
thread.start();
}
}
public class WorkFour {
public static void main(String[] args) {
Thread rabbit=new Thread(new Runnable() {
@Override
public void run() {
for (int i=0;i<=1000;i+=5){
System.out.println("兔子"+i);
if (i==1000){
System.out.println("兔子胜利");
System.exit(0);
}
if (i%20==0&&i!=0){
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
});
Thread tortoise=new Thread(new Runnable() {
@Override
public void run() {
for (int i = 0; i <= 1000; i++) {
System.out.println("乌龟"+i);
if (i==1000){
System.out.println("乌龟胜利");
System.exit(0);
}
if (i%100==0&&i!=0){
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
});
rabbit.start();
tortoise.start();
}
}
总结
1.为什么用多线程
将一些占用时间长的任务放到后台去运行,来减少程序运行时间,提高程序的运行效率
2.如不执行start直接调用重写或实现的run方法会怎样?
在没有执行start,直接调用run方法,不会创建新的线程,直接在主线程中运行



