JAVA基础-多线程-上

发布于 2024-07-28  114 次阅读


进程与线程

*程序:无任何运行含义,是一个静态的概念

*进程:执行程序的一次执行过程

*线程:CPU调度和执行的单位,一个进程中可以包含若干个线程

进程中有main(主方法)线程、gc线程(垃圾回收),main()为主线程,程序入口

一个CPU一次只能执行单个线程,多线程=多CPU(多核)

线程状态

1.创建状态:Tread t = new Thread()创建线程

2.就绪状态:调用t.start()方法,进入就绪状态,但是并没有被CPU调度执行

3.运行状态:被CPU调度执行线程体的代码块

4.阻塞状态:调用t.sleep(),t.wait()或同步锁定时,代码不继续往下执行,阻塞时间结束后,重新进入就绪状态等待CPU调度执行

5.死亡状态:线程中断或结束。一旦死亡就不能再次启动。

线程创建

创建方式:继承Thread类、实现Runanable接口、实现Callable接口

Thread类创建进程

重写run方法,通过start异步调用run方法启动线程

class test extends Thread{
    public void run(){
        for(int i=0 ; i<100 ; i++){
            System.out.println("BBBBBBBBBBBBBB");
        }
    }
}
public class Threads{
    public static void main(String args&#91;]){
        new test().start();
        for(int i=0 ; i<100 ; i++){
            System.out.println("AAAAAAAAAAAAAA");
        }
}}

结果中AAAAAAAA与BBBBBBBBBB随机排布,说明test类中创建的线程是和main中的线程是交替执行的,具体执行逻辑由CPU分配。

利用多线程同时下载多个文件

import org.apache.commons.io.FileUtils;

import java.io.File;
import java.io.IOException;
import java.net.URL;

class download extends Thread{
    String url;
    String name;
    public download(String url,String name){
        this.url = url;
        this.name = name;
    }
    public void run(){

        try {
            FileUtils.copyURLToFile(new URL(url), new File(name));
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        System.out.printf("下载了文件%s\n",name);
    }

    public static void main(String a&#91;]){
        new download("https://mak4r1.com/wp-content/uploads/2024/07/1722136018-204a4d6d5d6dd8064ebd140cfb9c5dfc-1536x1536.jpg","图片1.jpg").start();
        new download("https://mak4r1.com/wp-content/uploads/2024/07/1722136022-a07ce38bd1f99922e5d61d4ad641f159-1536x1536.jpg","图片2.jpg").start();
        new download("https://mak4r1.com/wp-content/uploads/2024/07/1722136022-61df6e36021b106e697cf59365d1c5ed-1536x1536.jpg","图片3.jpg").start();
        new download("https://mak4r1.com/wp-content/uploads/2024/07/1722136024-23f63fb11203d159c8e2ed725b2efc8e-1536x1536.jpg","图片4.jpg").start();

    }
}

实现Runnable接口

实现Runnable接口的类重写run方法,实例作为参数传给new Thread并执行start()

public class testRunnable implements Runnable{
    public void run(){
        System.out.println("Test Runnable");

    }
    public static void main(String a[]){
        new Thread(new testRunnable()).start();
    }
}

可以利用lambda表达式,表达的是run方法

public class testRunnable{

    public static void main(String a&#91;]){
        new Thread(()-> {System.out.println("Test Runnable");}).start();
    }
}

实现Callable接口

执行run方法返回Boolean类型,使用线程时创建线程池服务并提交线程对象,开启线程,停止服务。

import org.apache.commons.io.FileUtils;

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

class download implements Callable<Boolean> {
    String url;
    String name;
    public download(String url,String name){
        this.url = url;
        this.name = name;
    }
    public Boolean call(){

        try {
            FileUtils.copyURLToFile(new URL(url), new File(name));
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        System.out.printf("下载了文件%s\n",name);
        return true;
    }

    public static void main(String a&#91;]) throws ExecutionException, InterruptedException {
        download d1 = new download("https://mak4r1.com/wp-content/uploads/2024/07/1722136018-204a4d6d5d6dd8064ebd140cfb9c5dfc-1536x1536.jpg","图片1.jpg");
        download d2 = new download("https://mak4r1.com/wp-content/uploads/2024/07/1722136022-a07ce38bd1f99922e5d61d4ad641f159-1536x1536.jpg","图片2.jpg");
        download d3 = new download("https://mak4r1.com/wp-content/uploads/2024/07/1722136022-61df6e36021b106e697cf59365d1c5ed-1536x1536.jpg","图片3.jpg");
        download d4 = new download("https://mak4r1.com/wp-content/uploads/2024/07/1722136024-23f63fb11203d159c8e2ed725b2efc8e-1536x1536.jpg","图片4.jpg");

        ExecutorService ser = Executors.newFixedThreadPool(4);

        Future<Boolean> s1 = ser.submit(d1);
        Future<Boolean> s2 = ser.submit(d2);
        Future<Boolean> s3 = ser.submit(d3);
        Future<Boolean> s4 = ser.submit(d4);

        boolean rs1 = s1.get();
        boolean rs2 = s2.get();
        boolean rs3 = s3.get();
        boolean rs4 = s4.get();

        ser.shutdown();

    }
}

Runnable接口和Callable接口的实现,相当于对对象进行了一次静态代理(在其他类的方法中帮忙执行本类的方法)

并发问题

多个线程操作统一资源时产生的资源紊乱,导致进程不安全,例子:

public class testRunnable implements Runnable{
    static int apples = 10;
    public void run(){
        while (apples > 0){
            try {
                Thread.sleep(200);// 线程的模拟延时
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
            System.out.printf("%s吃掉了第%d个苹果。\n",Thread.currentThread().getName(),11-(apples--));
        }

    }
    public static void main(String a&#91;]){
        new Thread(new testRunnable(),"小明").start();
        new Thread(new testRunnable(),"小红").start();
        new Thread(new testRunnable(),"小兰").start();

}}

A web ctfer from 0RAYS
最后更新于 2024-08-24