Java多线程基础-第一节1:多线程概念和Java中创建线程的方式

Posted 我擦我擦

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java多线程基础-第一节1:多线程概念和Java中创建线程的方式相关的知识,希望对你有一定的参考价值。

文章目录

一:什么是线程和多线程

线程:关于进程和线程的概念这里就不再重复了,具体可见

要想进行下一步学习,你至少要清楚以下概念

  • 明白计算机的基本工作流程(冯诺依曼,寄存器、指令等概念)

  • 什么是进程,如何理解进程

  • 并行和并发

  • 进程PCB的概念

  • 进程调度与通信的概念

  • 什么是线程、为什么要引入线程

  • 进程和线程的区别

  • 线程调度

  • 用户级线程和内核级线程

  • 多线程的概念

二:Java多线程引入

  • 注意:不管是C++、Python还是Java,在多线程这一部分总是不太容易讲解,所以这里我们通过一个简单的例子来帮助大家理解

在之前的学习中,我们的代码只是运行在一个执行流中,如何证明?你会发现在这种单执行流中,不可能存在两个循环语句同时运行

  • 当你运行Java程序后,就会产生一个进程,此时main方法是该进程中唯一存在的一个线程,也即主线程,当有多个线程时mian方法就是所有线程的入口方法
  • 下面代码中Thread.sleep()用于将线程阻塞一定时间
public class Test 
    public static void main(String[] args) throws InterruptedException 
        while(true)
            System.out.println("main线程运行中");
            Thread.sleep(1000);
        
    

而在多线程中,由于线程之间是并发运行的,所以每个线程内部都可以独立的进行工作,所以对于整个进程或程序来说,它就可以同时运行多个循环语句

在Java中,会使用Thread类管理线程,用户在使用时线程时,需要自己实现一个线程类然后继承该Thread类,接着在内部重写run方法,run方法里面的逻辑,就是这个线程要执行的工作,如下

  • 注意:这仅是一种常见的创建线程的方式,还有其它方法,稍后说明
class MyThread extends Thread
    @Override
    public void run()
        while(true) 
            System.out.println("这是MyThread线程");
            try 
                Thread.sleep(1000);
             catch (InterruptedException e) 
                throw new RuntimeException(e);
            
        
    

创建线程时,直接实例化线程类即可,不过需要注意只有在调用start方法时,该线程才算被真正创建出来。如下,我们在main方法中实例化刚才的线程,然后在main方法内也写上一个循环语句

package threading;

class MyThread extends Thread
    @Override
    public void run()
        while(true) 
            System.out.println("这是MyThread线程");
            try 
                Thread.sleep(1000);
             catch (InterruptedException e) 
                throw new RuntimeException(e);
            
        
    


public class TestDemo 
    public static void main(String[] args) throws InterruptedException 
        MyThread myThread = new MyThread();
        myThread.start();
        while(true) 
            System.out.println("这是main线程");
            Thread.sleep(1000);
        
    

运行程序,你会发现两个循环在“交替”运行,这说明现在两个线程正在并发执行

多线程编程相较于普通编程难度会大大提高,稍有不慎就可能会导致整个系统崩溃。类似于任务管理器,为了方便我们对线程信息的掌控,Java提供了jconsole命令来观察线程

找到jdk安装目录,在bin文件下找到jconsole.exe,启动上面的程序后,双击jconsole.exe


在打开的窗口中选中对应的程序,然后点击连接

选择不安全的连接

进入监视窗口,选择线程


如下为线程运行信息,其中mainThread-0就是上面例子所展示的那两个线程。可以发现还有很多其他线程,它们各司其职,有负责垃圾回收的,有负责监视的,也有负责跟踪的等等

三:Java线程生命周期

Java线程生命周期:在Java中,一个线程会历经如下状态,分别有与之对应的操作或条件

  • 新建状态:使用关键字newThread类或其子类建立一个线程对象后,该线程就处于新建状态。它会保持这个状态直到程序start()这个线程
  • 就绪状态:当线程对象调用了start()方法后,该线程进入就绪状态。就绪状态的线程处于就绪队列中,等待JVM调度
  • 运行状态:如果就绪状态线程获取CPU资源,就可以执行run(),此线程便处于运行状态。处于运行状态的线程可以重新变为阻塞、就绪或死亡状态
  • 阻塞状态:如果一个线程执行了sleep(睡眠)、suspend(挂起)的等方法,失去所占用的资源后,就会进入阻塞状态。在睡眠时间已到或重新获得资源后可再次进入就绪状态。分为等待阻塞、同步阻塞或其他阻塞
  • 死亡状态:个运行状态的线程完成任务或者其他终止条件发生时,该线程就切换到终止状态

四:创建线程的方法

(1)通过继承Thread类

通过继承Thread类:格式如下,这种方法使线程和线程需要完成的任务绑定在了一起,直接使用this就表示当前线程对象的引用。所以这种写法耦合性太强,未来改动时代价较大

1:继承Thread类创建一个线程类
class MyThread extends Thread
	@override
	public void run()
		System.out.println("线程运行逻辑")
	


2:创建MyThread类实例
MyThread thread0 = new MyThread();

3:调用start方法启动线程
thread0.strat();

(2)通过实现Runnable接口

通过实现Runnable接口:格式如下,这种方法把线程和线程需要完成的任务分开了,使用Runnable专门表示线程需要完成的任务,此时this表示的是Runnbale对象的引用,如果要引用线程时则要借助Thread.currentThread()。所以这种写法耦合性较低,未来改动时代价较低

1:实现Runnable接口
class MyRunnable implements Runnable
    @Override
    public void run()
        System.out.println("线程运行逻辑");
    


2:创建Thread类实例,在调用Thread构造方法时将Runnable对象作为target参数
Thread thread0 = new Thread(new MyRunnable());

3:调用start方法
thread0.start();

例子

package threading;

class MyRunnable implements Runnable
    @Override
    public void run()
        while(true) 
            System.out.println("这是MyRunnable线程");
            try 
                Thread.sleep(1000);
             catch (InterruptedException e) 
                throw new RuntimeException(e);
            
        
    


public class TestDemo2 
    public static void main(String[] args) throws InterruptedException 
        Thread thread0 = new Thread(new MyRunnable());
        thread0.start();
        while(true) 
            System.out.println("这是main线程");
            Thread.sleep(1000);
        
    

(3)变种形式

①:使用匿名内部类创建Thread子类对象

package threading;

public class TestDemo3 
    public static void main(String[] args) throws InterruptedException 
        Thread thread = new Thread()
            @Override
            //匿名内部类
            public void run()
                while(true) 
                    System.out.println("这是MyThread线程");
                    try 
                        Thread.sleep(1000);
                     catch (InterruptedException e) 
                        throw new RuntimeException(e);
                    
                
            
        ;
        thread.start();

        while(true) 
            System.out.println("这是main线程");
            Thread.sleep(1000);
        
    

②:使用匿名内部类实现Runnable接口

package threading;

public class TestDemo4 
    public static void main(String[] args) throws InterruptedException 
        Thread thread = new Thread(
                //匿名内部类
                new Runnable() 
                    @Override
                    public void run() 
                        while(true) 
                            System.out.println("这是MyRunnable线程");
                            try 
                                Thread.sleep(1000);
                             catch (InterruptedException e) 
                                throw new RuntimeException(e);
                            
                        
                    
                
        );
        thread.start();

        while(true) 
            System.out.println("这是main线程");
            Thread.sleep(1000);
        
    

③:使用lambda表达式

package threading;

public class TestDemo5 
    public static void main(String[] args) throws InterruptedException 
        Thread thread0 = new Thread(
                () -> 
                    while(true) 
                        System.out.println("lambda表达式Thread");
                        try 
                            Thread.sleep(1000);
                         catch (InterruptedException e) 
                            throw new RuntimeException(e);
                        
                    
                
        );
        thread0.start();

        while(true) 
            System.out.println("这是main线程");
            Thread.sleep(1000);
        
    


五:多线程的优势

多线程的最大优势还是在于提高计算速度,如下分别使用串行和并发的方式完成同样的运算

package threading;

public class threadAdvantaged 
    //数字300亿
    public static final long COUNT = 200_0000_0000L;


    public static void main(String[] args) 
        serial_execution();

        concurrency_execution();
    

    //串行执行
    public static void serial_execution()
        long begin = System.currentTimeMillis();

        long a = 0;
        for (long i = 0; i < COUNT; i++)
            a++;
        

        a = 0;
        for (long i = 0; i < COUNT; i++)
            a++;
        

        long end = System.currentTimeMillis();
        System.out.println("串行执行用时:" + (end - begin) + "ms");
    

    //并发执行
    public static void concurrency_execution()
        long begin = System.currentTimeMillis();

        Thread thread1 = new Thread(
                new Runnable() 
                    @Override
                    public void run() 
                        long a = 0;
                        for (long i = 0; i < COUNT; i++)
                            a++;
                        
                    
                
        );
        Thread thread2 = new Thread(
                new Runnable() 
                    @Override
                    public void run() 
                        long a = 0;
                        for (long i = 0; i < COUNT; i++)
                            a++;
                        
                    
                
        );

        thread1.start();
        thread2.start();

        //阻塞
        try
            thread1.join();
            thread2.join();
        catch (InterruptedException e)
            e.printStackTrace();
        

        long end = System.currentTimeMillis();
        System.out.println("并发执行用时:" + (end - begin) + "ms");

    


以上是关于Java多线程基础-第一节1:多线程概念和Java中创建线程的方式的主要内容,如果未能解决你的问题,请参考以下文章

Java多线程基础-第一节6:多线程案例

Java多线程基础-第一节5:wait和notify

Java多线程基础-第一节2:Thread类

Java多线程基础-第一节4:synchronized关键字(监视器锁monitor lock)和volatile关键字

java多线程编程(一基础概念)

Java多线程常见面试题-第一节:锁策略CAS和Synchronized原理