提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档


文章目录

  • 一、进程是什么?
  • 二、线程是什么?
  • 三、线程和进程区别是什么?
  • 四、串行,并行,并发的区别
  • 五、线程实现的几种方法
  • 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终止状态

java线程执行时间限制多久 java线程执行完_java线程执行时间限制多久

线程常用方法

方法名

作用

start

启动线程

stop

停止线程 禁用 可能出现死锁问题

getName

得到线程名

setName

更改线程名

sleep(毫秒)

睡眠,毫秒

setPriority

设置优先级(1到10级)

setDaemon(true)

设置后台线程,案例GC

jion()

插队

线程小案例

题目一

  1. 设计两个线程,一个线程负责打印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);
    }
}

题目二

  1. 实现一个线程,用于扫描某个目录下的所有文本文件(包括: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();
    }

}

题目四

  1. 多线程模拟龟兔赛跑:

乌龟和兔子进行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调度的基本的最小单位