Java并发之线程入门一

Posted 笑霸final

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java并发之线程入门一相关的知识,希望对你有一定的参考价值。

前言
👏作者简介:我是笑霸final,一名热爱技术的在校学生。
📝个人主页:笑霸final的主页
📕系列专栏::本文写在java专栏
📧如果文章知识点有错误的地方,请指正!和大家一起学习,一起进步👀
🔥如果感觉博主的文章还不错的话,请👍三连支持👍一下博主哦

Java并发之线程入门

一、什么是线程?

线程(英语: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接口创建线程

继承关系

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=0;i<100;++i)
            System.out.println(i);
            try 
                Thread.sleep(1000);
             catch (InterruptedException e) 
                e.printStackTrace();
            
        
    


//1.该类继承了Thread 该类就可以当成线程使用
//2.重写run,添加自己的业务逻辑


class Cat extends Thread
    @Override
    public void run() //重写run,添加自己的业务逻辑
        //每个1秒 输出喵喵
       while(true)
           System.out.println("喵喵");
           //让线程休眠1秒
           try 
               Thread.sleep(500);//抛出异常快捷键 ctrl+alt+t
            catch (InterruptedException e) 
               e.printStackTrace();
           
       
    

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


以上代码可以看出 有两个线程,每一个线程都在执行循环,所以这个程序在同时执行两个线程(现在在宏观上这么理解,后面有机会讲并发和并行)
注意不能直接调用run方法。如果直接调用他不会创建一个新的线程。

问题😕/假如Cat已经继承了其他类 我要实现多线程怎么办?
所以还能实现Runnable接口方式创建多线程。

2.1.1实现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();
    

2.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");
    



class MyThread extends Thread 
    public void run() 
        int n = 0;
        while (! isInterrupted()) 
            n ++;
            System.out.println(n + " hello!");
        
    




四、线程属性

4.1线程优先级

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

代码:

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=1;i<=10;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=1;j<=10;j++)
            System.out.println("我来了"+j);
            try 
                Thread.sleep(1000);
             catch (InterruptedException e) 
                e.printStackTrace();
                
            if(j==10)
                    System.out.println("子线程退出了");

            
        
    


以上是关于Java并发之线程入门一的主要内容,如果未能解决你的问题,请参考以下文章

(大厂必备)厂长熬夜爆肝万字之多线程高并发JUC编程⭐学妹已收藏

(大厂必备)厂长熬夜爆肝万字之多线程高并发JUC编程⭐学妹已收藏

Java多线程视频教程并发编程面试知识

Java并发入门之互斥锁-解决原子性问题

Java小白入门200例112之Java HashSet类

Java并发之ThreadPoolExecutor