Java线程

Posted 小郑要做干饭人

tags:

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

1.什么是进程?

  进行运行的程序叫做进程,进程是系统分配资源的基本单位,使用PID来区别进程

2.什么是线程?

线程是进程中的一条执行路径,也是CPU的基本调度单位。一个进程有一个或多个线程组成,彼此间完成不同的工作,同时执行,称为多线程。

3.进程和线程的区别

    (1)进程是操作系统资源分配的基本单位,而线程是CPU的基本调度单位。

    (2)一个程序运行后至少有一个进程

    (3)一个进程可以包含多个线程,但是只有需要有一个线程,否则这个进程是没有意义。

    (4)进程间不能共享数据段地址,但是同进程的线程之间可以。

4.为什么使用线程

为了解决负载均衡问题,充分利用CPU资源,为了提高CPU的使用率,采用多线程的方式去同时完成几件事情而互不干扰,为了处理大量的IO操作时或处理的情况需要花费大量的时间等等,比如:读写文件,视频图像 的采集,处理,显示,保存等

单核时代: 在单核时代多线程主要是为了提高 CPU 和 IO 设备的综合利用率。举个例子:当只有一个 线程的时候会导致 CPU 计算时,IO 设备空闲;进行 IO 操作时,CPU 空闲。我们可以简单地说这两者 的利用率目前都是 50%左右。但是当有两个线程的时候就不一样了,当一个线程执行 CPU 计算时,另外 一个线程可以进行 IO 操作,这样两个的利用率就可以在理想情况下达到 100%了。

多核时代: 多核时代多线程主要是为了提高 CPU 利用率。举个例子:假如我们要计算一个复杂的任务, 我们只用一个线程的话,CPU 只会一个 CPU 核心被利用到,而创建多个线程就可以让多个 CPU 核心被 利用到,这样就提高了 CPU 的利用率

5.Java如何创建线程

方式一:继承Thread类:

package com.zzx.线程;

/**
 * @date: 2022/08/10/ 22:24
 * @author: ZhengZiXuan
 * @title: 通过继承Thread类来实现线程,调用run/start方法
 * @description:
 */
public class ThreadTest extends Thread //此处按住Ctrl+鼠标左键点击进入源码,发现Thread类实现了Runnable接口(如图一所示)
    @Override
    public void run() 
        for (int i = 0; i < 100; i++) 
            System.out.println("我在听课"+i);
        
    


class Test
    public static void main(String[] args) 
        ThreadTest threadTest = new ThreadTest();
        threadTest.start();
        for (int i = 0; i < 2000; i++) 
            System.out.println("我在看代码"+i);

        

    


运行start方法,控制台打印结果:

通过控制台运行结果可看出,当调用start方法时,两条线程是同时执行的

package com.zzx.线程;

/**
 * @date: 2022/08/10/ 22:24
 * @author: ZhengZiXuan
 * @title: 通过继承Thread类来实现线程,调用run/start方法
 * @description:
 */
public class ThreadTest extends Thread
    @Override
    public void run() 
        for (int i = 0; i < 100; i++) 
            System.out.println("我在听课"+i);
        
    


class Test
    public static void main(String[] args) 
        ThreadTest threadTest = new ThreadTest();
        threadTest.run();
        for (int i = 0; i < 2000; i++) 
            System.out.println("我在看代码"+i);

        

    



// 总结: 线程开启不一定立即执行,由CPU调度执行


当调用run方法时,我们可以发现两个线程是顺序执行的,也就是第一条线程执行完之后,第二条线程才会执行,以此类推


附带:Thread小练习(网图下载)

方式二: 实现Runnable接口

package com.zzx.线程.Runnable;

/**
 * @date: 2022/08/15/ 22:13
 * @author: ZhengZiXuan
 * @title:
 * @description: 实现Runnable接口,重写run方法,执行线程需要丢入Runnable接口实现类,调用start方法
 */
public class RunnableTest implements Runnable

    public void run() 
        for (int i = 0; i < 1000; i++) 
            System.out.println("我正在学习Runnable,第: " + i + " 次~~~");
        
    


class Test
    public static void main(String[] args) 
        //创建Runnable接口的实现类对象
        RunnableTest runnableTest = new RunnableTest();
        //创建线程对象,通过线程对象来开启我们的线程,代理
        Thread thread = new Thread(runnableTest); //此处按住Ctrl+鼠标左键点击进入,查看其构造器(如图一所示)发现参数需要一个目标的Runnable接口
        thread.start();
        for (int i = 0; i < 1000; i++) 
            System.out.println("魏武遗风: "+ i + " 曹操~~~");

        
        //runnableTest.run();
    



运行start方法,控制台打印结果:

通过运行我们发现,当调用run方法时,线程是同时执行的
Runnable小练习(网图下载)

方式三: 实现Callable接口:

package com.zzx.线程.Callable;


import org.apache.commons.io.FileUtils;

import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.util.concurrent.*;

/**
 * @date: 2022/08/17/ 22:02
 * @author: ZhengZiXuan
 * @title: 方式三: 实现callable接口
 * @description:
 */
public class CallableTest implements Callable<Boolean> 

    //网络图片地址
    private String url;

    //保存的文件名
    private String name;


    public Boolean call() 
        WebDownloader webDownloader = new WebDownloader();
        webDownloader.downLoader(url,name);
        System.out.println("下载了文件名为:"+name);
        return true;
    

    public CallableTest(String url,String name) 
        this.name=name;
        this.url = url;
    

    public static void main(String[] args) throws ExecutionException, InterruptedException 
        CallableTest c1 = new CallableTest("https://nimg.ws.126.net/?url=http%3A%2F%2Fdingyue.ws.126.net%2F2021%2F0731%2Fe91198a9j00qx35q30050c000j600nym.jpg&thumbnail=660x2147483647&quality=80&type=jpg","小姐姐1.jpg");
        CallableTest c2 = new CallableTest("https://nimg.ws.126.net/?url=http%3A%2F%2Fdingyue.ws.126.net%2F2020%2F0308%2Faa2f8437j00q6uv1c001fc000hs00hsm.jpg&thumbnail=660x2147483647&quality=80&type=jpg","小姐姐2.jpg");
        CallableTest c3 = new CallableTest("https://nimg.ws.126.net/?url=http%3A%2F%2Fdingyue.ws.126.net%2F2020%2F0308%2F94d8bda3j00q6uv1e000oc000hs00m7m.jpg&thumbnail=660x2147483647&quality=80&type=jpg","小姐姐3.jpg");

        //创建执行服务
        ExecutorService executorService = Executors.newFixedThreadPool(3); //创建三个线程

        //提交执行
        Future<Boolean> result1 = executorService.submit(c1);
        Future<Boolean> result2 = executorService.submit(c2);
        Future<Boolean> result3 = executorService.submit(c3);

        //获取结果
        boolean b1 = result1.get();
        boolean b2 = result2.get();
        boolean b3 = result3.get();
        System.out.println("b1:"+ b1);
        System.out.println("b2:"+ b2);
        System.out.println("b3:"+ b3);


        //关闭服务
        executorService.shutdown();

    

//下载器
class WebDownloader
    //下载方法
    public void downLoader(String pictureUrl, String name)
        try 
            FileUtils.copyURLToFile(new URL(pictureUrl),new File(name));
         catch (IOException e) 
            e.printStackTrace();
            System.err.println("IO异常,downloader方法出现问题");
        
    


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

java并发

你懂Java多线程吗Java多线程技能

Java多线程面试

Java多线程——基本概念

java线程

JAVA 多线程