zl程序教程

您现在的位置是:首页 >  后端

当前栏目

Java并发之线程入门一

2023-09-27 14:25:58 时间
一、什么是线程


线程 英语 thread 是操作系统能够进行运算调度的最小单位。它被包含在进程之中 是进程中的实际运作单位。一条线程指的是进程中一个单一顺序的控制流 一个进程中可以并发多个线程 每条线程并行执行不同的任务。在Unix System V及SunOS中也被称为轻量进程 lightweight processes 但轻量进程更多指内核线程 kernel thread 而把用户线程 user thread 称为线程。


线程是独立调度和分派的基本单位.线程可以为操作系统内核调度的内核线程 如Win32线程 由用户进程自行调度的用户线程 如Linux平台的POSIX Thread 或者由内核与用户进程 如Windows 7的线程 进行混合调度。同一进程中的多条线程将共享该进程中的全部系统资源 如虚拟地址空间 文件描述符和信号处理等等。但同一进程中的多个线程有各自的调用栈 call stack 自己的寄存器环境 register context 自己的线程本地存储 thread-local storage 。


一个进程可以有很多线程 每条线程并行执行不同的任务。


在多核或多CPU 或支持Hyper-threading的CPU上使用多线程程序设计的好处是显而易见 即提高了程序的执行吞吐率。在单CPU单核的计算机上 使用多线程技术 也可以把进程中负责I/O处理、人机交互而常被阻塞的部分与密集计算的部分分开来执行 编写专门的workhorse线程执行密集计算 从而提高了程序的执行效率。


二、线程状态


线程有6种状态


1.New(新创建)


2.Runnable(可运行)


3.Blocked(被阻塞)


4.Waiting(等待)


5.Timed wating(计时等待)


6.Terminated(被终止)


要确定一个线程状态。可以调用getState方法


2.1、创建新的线程


常用的创建方式


1 继承Thread类创建线程


2 实现Runnable接口创建线程


继承关系

c7490581d2fe4c45ac52a2a2e77bb163.png

2.1.1继承Thread类创建线程


第一步 创建一个类T 使它继承Thread


class T extends Thread{}


第二步骤 重写run方法


Override public void run(){这里写自己的逻辑方法}


第三步 创建Cat的实例 然后启动线程 即调用线程的start方法


T t new T(); t.start();


调用start();就会创建一个新的线程 它会执行刚刚重写的run方


代码实列

package com.final_.thread01;

 * autor 笑霸fianl~

 * 欢迎访问GitHub https://github.com/XBfinal

 * 欢迎访问Gitee https://gitee.com/XBfianl

 * 欢迎访问CSDN https://blog.csdn.net/weixin_52062043

 * 演示通过继承Thread类创建线程

public class Thread01 {

 //创建一个CAT对象

 public static void main(String[] args) {

 Cat cat new Cat();

 /******************************/

 cat.start();

 //start就是启动了一个新的线程 程序不会阻塞在这里 还会继续执行main线程

 System.out.println( 主线程不会阻塞 继续执行 Thread.currentThread().getName());

 for(int i i i){

 System.out.println(i);

 try {

 Thread.sleep(1000);

 } catch (InterruptedException e) {

 e.printStackTrace();

//1.该类继承了Thread 该类就可以当成线程使用

//2.重写run 添加自己的业务逻辑


/*****************************************************/ //假如Cat已经继承了其他类 我要实现多线程怎么办


4e21cafb67c24b3296f36b84e48f4be8.png


以上代码可以看出 有两个线程 每一个线程都在执行循环 所以这个程序在同时执行两个线程 现在在宏观上这么理解 后面有机会讲并发和并行


注意不能直接调用run方法。如果直接调用他不会创建一个新的线程。


问题 /假如Cat已经继承了其他类 我要实现多线程怎么办


所以还能实现Runnable接口方式创建多线程。


2.1.2实现Runnable接口创建线程


1.定义一个类实现Runnable接口 一样要重写run()方法 这个run 方法和Thread中的run()方法一样.


class Dog implements Runnable{

 Override

 public void run() {

 while(true){

 System.out.println( 小狗汪汪叫 

 //休眠1秒

 try {

 Thread.sleep(500);

 } catch (InterruptedException e) {

 e.printStackTrace();

}


2.创建实例,并运行


注意这里不能直接调用start方法 接口没有start方法 但是也不不能直接调用run方法


所以可以间接调用下列代码


public class Thread02 {

 public static void main(String[] args) {

 Dog dog new Dog();

 //dog.start

 //不行了 接口没有start方法 但是也不不能直接调用run方法

 //所以可以把dog放入Thread中

 Thread thread new Thread(dog);//这里使用了静态代理模式

 thread.start();

}


66b3d8e549fd4e2b9a9f98e4e0d3180a.png

66b3d8e549fd4e2b9a9f98e4e0d3180a.png2.2可运行的线程

一旦调用star方法 该线程就处于Runnable(可运行)状态 一个可运行线程是否运行要看系统提供运行的时间


记住在给定时间内 可运行线程可能运行 也可能没有运行 所以这叫可运行线程 不见运行线程


2.3等待线程


调用Thread.sleep();可以让线程等待单位是毫秒


注意此处有异常抛出


 try {

 Thread.sleep(1000);

 } catch (InterruptedException e) {

 e.printStackTrace();

 }


当然也可以thows。


2.4被终止的线程


原因1.run方法自然死亡或者正常退出


原因2.没有捕获异常终止了run方法而意外死亡


相关的方法


void join()//等待终止线程

void join(long millis)//等待终止线程或者经过指定的毫秒数


三、中断线程


中断 Interrupt 一个线程意味着在该线程完成任务之前停止其正在进行的一切 有效地中止其当前的操作。 线程是死亡、还是等待新的任务或是继续运行至下一步 就取决于这个程序。 虽然初次看来它可能显得简单 但是 你必须进行一些预警以实现期望的结果。


void interrrupt())//向线程发送中断请求。线程的中断状态将会被设置为true


package com.final_.thread01;

 * autor 笑霸fianl~

 * 欢迎访问GitHub https://github.com/XBfinal

 * 欢迎访问Gitee https://gitee.com/XBfianl

 * 欢迎访问CSDN https://blog.csdn.net/weixin_52062043

public class T03 {

 public static void main(String[] args) throws InterruptedException {

 Thread t new MyThread();

 t.start();

 Thread.sleep(1); // 暂停1毫秒

 t.interrupt(); // 中断t线程

 t.join(); // 等待t线程结束

 System.out.println( end 


66b3d8e549fd4e2b9a9f98e4e0d3180a.png

四、线程属性


4.1线程优先级


如果有几个高优先级的线程没有进入非活动状态 低优先级的线程可能永远不会执行 尽管会让低优先级的线程饿死 系统也会在高优先级的线程中选择。


55d4535b1a2f4080b1f4e4deef71738c.png


代码


public static void main(String[] args) {

 System.out.println(Thread.currentThread().getPriority());

}


4.2守护线程


线程可以是守护线程或用户线程。


唯一的作用守护线程是服务提供者线程。


我们可以通过使用setDaemon()方法通过传递true作为参数 使线程成为一个守护线程。


守护线程应该永远不去访问固有资源 因为它会在任何的时候甚至在一个操作的中间发生中断


源代码


//这一个方法必须在线程启动之前调用

 public final void setDaemon(boolean on) {

 checkAccess();

 if (isAlive()) {

 throw new IllegalThreadStateException();

 daemon on;

 }
练习


主线程每隔1秒输出 i你好 一共10次


当主线程输出到 i 5时 启动一个子线程 用Runnable)实现 每隔1秒输出我来了j j 10 退出 主线程继续输出


代码


package com.fianl_.ThreadMethod;

 * autor 笑霸fianl~

 * 欢迎访问GitHub https://github.com/XBfinal

 * 欢迎访问Gitee https://gitee.com/XBfianl

 * 欢迎访问CSDN https://blog.csdn.net/weixin_52062043

 * 主线程每隔1秒输出 i你好 一共10次

 * 当主线程输出到 i 5时 启动一个子线程 用Runnable)实现 每隔1秒输出 我来了j j 10 退出

 * 主线程继续输出

 * */

public class exercise {

 public static void main(String[] args) throws InterruptedException {

 T1 t1 new T1();

 for(int i i i ){

 System.out.println(i 你好 

 Thread.sleep(1000);

 if(i 5){

 //记住不能直接用t1.start();

 Thread thread new Thread(t1);

 thread.start();

 thread.join();

class T1 implements Runnable{

 Override

 public void run() {

 for(int j j j ){

 System.out.println( 我来了 

 try {

 Thread.sleep(1000);

 } catch (InterruptedException e) {

 e.printStackTrace();

 if(j 10){

 System.out.println( 子线程退出了 


c2b935ea5b5145a7a96eeda208fb9b34.png


Java 学习之入门springBoot # 简介 SpringBoot是Pivotal团队提供的全新框架,其设计目的来简化Spring应用的初始搭建以及开发过程。 ## 对比之前的框架 笔者之前也学习应用过很多框架,包括Spring,SpringMVC,MyBatis等等....... 拿SpringMVC来举例,在SpingMVC中配置了处理请求的时候,会遇到静态资源无法访问的问题,这是因为我们对于getSeverletMappings中的设置是控制所有的路由,那么这问题就来了,我们对于访问静态资源这个事情,并不会经手Tomcat,而是经过SpringMVC,他会直接拦截我们的请求,而拦截后springMVC会发现我们并没