首页 > 其他分享 >线程

线程

时间:2024-07-03 23:08:43浏览次数:1  
标签:void System 线程 println new public

线程

普通方法调用和多线程

Process和Thread

  • 程序是指令和数据的有序集合,是静态概念
  • 进程Process是执行程序的一次执行过程,是一个动态的概念,是系统资源分配的单位
  • 通常一个进程中可以包含多个线程,每个进程中至少有一个线程,线程是CPU调度和执行的单位

核心概念

  • 线程是独立的执行路径
  • 程序运行时,即使没有自己创建线程,后台也会有多个线程,如主线程,gc线程(清理)
  • main()称为主线程,是系统的入口,用于执行整个程序
  • 一个进程中,如开辟了多个线程,线程的运行由调度器安排
  • 对一份资源进行操作时,会存在资源抢夺的问题,需要加入并发控制
  • 线程会带来额外的开销,如CPU调度时间,并发控制开销
  • 每个线程在自己的工作内存交互,内存控制不当会造成数据不一致

线程创建

Thread类(重点)

  • 自定义线程类继承Thread类
  • 重写run()方法,编写线程执行体
  • 创建线程对象,调用start()方法开启线程
package OOP.Demo;

/**
 * @version: java version 1.8
 * @Author: 14
 */
public class Thread01 extends Thread{
    //创建线程方式一: 继承Thread类,重写run方法,调用start开启线程
    //总结:线程开启不一定立即执行,由CPU调度
    @Override
    public void run() {//重写run方法
        for (int i = 0; i <500 ; i++) {
            System.out.println("这里是线程01");
        }
    }
    public static void main(String[] args) {//main线程,主线程
        //创建线程对象
        Thread01 t1 = new Thread01();
        //调用start();开启线程
        t1.start();
        for (int i = 0; i < 1000; i++) {
            System.out.println("这里是main");
        }
    }
}

例子:下载图片测试

package OOP.Demo;

import org.apache.commons.io.FileUtils;

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

/**
 * @version: java version 1.8
 * @Author: 14
 */
public class Thread02 extends Thread{

    private String Url;
    private String path;

    public Thread02(String Url,String path){
        this.Url = Url;
        this.path = path;
    }

    @Override
    public void run() {
        new WebDownloader().downloader(Url,path);
//        WebDownloader webDownloader = new WebDownloader();
//        webDownloader.downloader(Url,path);
        System.out.println("下载了文件在:"+path);
    }


    public static void main(String[] args) {
        Thread02 t1 = new Thread02("/i/l/?n=24&i=blog/3475380/202407/3475380-20240701154652288-1747217106.png","1.png");
        Thread02 t2 = new Thread02("/i/l/?n=24&i=blog/3475380/202407/3475380-20240701154705043-664732010.png","2.png");
        Thread02 t3 = new Thread02("/i/l/?n=24&i=blog/3475380/202407/3475380-20240701154710607-423679454.png","3.png");

        t1.start();
        t2.start();
        t3.start();
    }
}
class WebDownloader{
    public void downloader(String url,String path){
        try {
            FileUtils.copyURLToFile(new URL(url),new File(path));
        } catch (IOException e) {
            e.printStackTrace();
            System.out.println("IOException");
        }
    }
}

Runnable接口(重点)

  • 定义MyRunnable类实现Runnable接口

  • 实现run()方法,编写线程执行体

  • 创建线程对象,调用start()方法启动线程

    推荐使用Runnable对象,因为Java单继承的局限性

package OOP.Demo;

/**
 * @version: java version 1.8
 * @Author: 14
 */
public class Thread03 implements Runnable{
    @Override
    public void run() {
        for (int i = 0; i <500 ; i++) {
            System.out.println("这里是线程01");
        }
    }
    public static void main(String[] args) {//main线程,主线程
        //创建线程对象
        Thread03 t1 = new Thread03();
        //调用start();开启线程
        new Thread(t1).start();//区别在这

        for (int i = 0; i < 1000; i++) {
            System.out.println("这里是main");
        }
    }
}

例子:购买火车票

package OOP.Demo;

/**
 * @version: java version 1.8
 * @Author: 14
 */

//多个线程同时操作一个对象
//买火车票例
//发现问题:多个线程操作同一个资源,线程不安全,数据紊乱
public class Thread04 implements Runnable{

    //票数
    private int ticketNums = 10;
    @Override
    public void run() {
        while (true) {
            if(ticketNums>0){
                System.out.println(Thread.currentThread().getName()+"->拿到了第"+ticketNums--+"票");
            }else {
                break;
            }
            //模拟延时
            try {
                Thread.sleep(200);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
    public static void main(String[] args) {
        Thread04 t4 = new Thread04();

        new Thread(t4,"小红").start();
        new Thread(t4,"小米").start();
        new Thread(t4,"万恶的黄牛").start();
    }
}

image-20240703172401393

例子:龟兔赛跑

image-20240703210445563

package OOP.Demo;

/**
 * @version: java version 1.8
 * @Author: 14
 */
public class Race implements Runnable{

    static String winner = null;
    @Override
    public void run() {
        for (int i = 0; i <= 100; i++) {
            if (Thread.currentThread().getName().equals("兔子") && i%11 == 0) {
                try {
                    Thread.sleep(1);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            if (winner(i)){
                break;
            }
            System.out.println(Thread.currentThread().getName() + "跑了" + i + "步");
        }
    }
    public boolean winner(int steps){

        if(winner != null){
            return true;
        }
        if(steps >= 100){
            winner = Thread.currentThread().getName();
            System.out.println("胜者是:" + winner);
            return true;
        }
        return false;
    }

    public static void main(String[] args) {
        Race race = new Race();
        new Thread(race,"兔子").start();
        new Thread(race,"乌龟").start();
    }
}

Callable接口

  • 实现Callable接口,需要返回值类型

  • 重写call()方法,需要抛出异常

  • 创建目标对象

  • 创建执行服务:

    ExecutorService ser = Executors.newFixedThreadPool(1);
    
  • 提交执行:

    Future<Boolean> result = ser.submit(t1);
    
  • 获取结果:

    boolean r = result.get();
    
  • 关闭服务:

    ser.shutdownNow();
    

例子:利用Callable改造下载图片案例

package OOP.Demo;

import org.apache.commons.io.FileUtils;

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

/**
 * @version: java version 1.8
 * @Author: 14
 */
public class Thread05 implements Callable<Integer> {

    private String Url;
    private String path;

    public Thread05(String Url,String path){
        this.Url = Url;
        this.path = path;
    }

    @Override
    public Integer call() {
        new WebDownloader().downloader(Url,path);
//        WebDownloader webDownloader = new WebDownloader();
//        webDownloader.downloader(Url,path);
        System.out.println("下载了文件在:"+path);
        return 0;
    }


    public static void main(String[] args) throws ExecutionException, InterruptedException {
        Thread05 t1 = new Thread05("/i/l/?n=24&i=blog/3475380/202407/3475380-20240701154652288-1747217106.png","1.png");
        Thread05 t2 = new Thread05("/i/l/?n=24&i=blog/3475380/202407/3475380-20240701154705043-664732010.png","2.png");
        Thread05 t3 = new Thread05("/i/l/?n=24&i=blog/3475380/202407/3475380-20240701154710607-423679454.png","3.png");

//        t1.start();
//        t2.start();
//        t3.start();
        //创建服务
        ExecutorService ser = Executors.newFixedThreadPool(3);
        //提交执行
        Future<Integer> f1 = ser.submit(t1);
        Future<Integer> f2 = ser.submit(t2);
        Future<Integer> f3 = ser.submit(t3);
        //获取结果
        Integer r1 = f1.get();
        Integer r2 = f2.get();
        Integer r3 = f3.get();
        //打印结果
        System.out.println(r1);
        System.out.println(r2);
        System.out.println(r3);
        //关闭服务
        ser.shutdownNow();
    }

}
//class WebDownloader{
//    public void downloader(String url,String path){
//        try {
//            FileUtils.copyURLToFile(new URL(url),new File(path));
//        } catch (IOException e) {
//            e.printStackTrace();
//            System.out.println("IOException");
//        }
//    }
//}

Lambda表达式

  • 函数式接口:

    任何接口,如果只包含唯一的一个抽象方法,那么它就是函数式接口

    public interface Runnable{
        public abstract void run();
    }
    
  • 对于函数式接口,我们可以通过lambda表达式来创建该接口的对象

package OOP.Demo;

/**
 * @version: java version 1.8
 * @Author: 14
 */
public class LambdaTest {
    //3、静态内部类
    static class ILove1 implements Love{
        @Override
        public void love() {
            System.out.println("I LOVE -->1");
        }
    }

    public static void main(String[] args) {
        //4、局部内部类
        class ILove2 implements Love{
            @Override
            public void love() {
                System.out.println("I LOVE -->2");
            }
        }
        ILove iLove3 = new ILove();
        //5、匿名内部类
        iLove3 = new ILove(){
            @Override
            public void love() {
                System.out.println("I LOVE -->3");
            }
        };
        //6、Lambda表达式
        Love iLove4 = ()-> { System.out.println("I LOVE -->4"); };

        ILove iLove = new ILove();
        ILove1 iLove1 = new ILove1();
        ILove2 iLove2 = new ILove2();
        iLove.love();
        iLove1.love();
        iLove2.love();
        iLove3.love();
        iLove4.love();
    }
}

//1、定义函数式接口
interface Love {
    void love();
}
//2、实现类
class ILove implements Love{
    @Override
    public void love() {
        System.out.println("I LOVE -->0");
    }
}

Lambda简化

总结

  • lambda表达式只有一行代码的情况下,才能简化为一行,如有多行,需要花括号包裹
  • 使用lambda表达式的前提是 接口为函数式接口
  • 多个参数也可以去掉参数类型(要去就都去掉),用括号包裹
package OOP.Demo;

/**
 * @version: java version 1.8
 * @Author: 14
 */
public class LambdaTest {
    public static void main(String[] args) {
        //Lambda表达式
        Love iLove = ()-> { System.out.println("I LOVE -->0"); };
        //Lambda简化
        Love1 iLove1 = a ->  System.out.println("I LOVE -->" + a);

        Love2 iLove2 = (a,b) -> {
            System.out.println("I LOVE -->" + a);
            System.out.println("I LOVE -->" + b);
        };

        iLove.love();
        iLove1.love1(1);
        iLove2.love2(2,3);
    }
}

//1、定义函数式接口
interface Love {
    void love();
}
interface Love1{
    void love1(int a);
}
interface Love2{
    void love2(int a, int b);
}

静态代理模式(线程的底部原理)

总结:

  • 真实对象和代理对象都要实现同一个接口

  • 代理对象必须要代理真实对象

好处:

  • 代理对象可以做很多真实对象做不了的事情

  • 真实对象专注做自己的事情

package OOP.Demo;

/**
 * @version: java version 1.8
 * @Author: 14
 */
public class StaticProxy {
    public static void main(String[] args) {
        Person person = new Person();
        MarryCompany marryCompany = new MarryCompany(person);
        marryCompany.marry();
        //线程启动,也相当与静态代理
        new Thread(()-> System.out.println("这是一个线程")).start();
        new MarryCompany(new Person()).marry();
    }
}

interface Marry{
    void marry();
}
class Person implements Marry{
    @Override
    public void marry() {
        System.out.println("找到漂亮老婆结婚啦!!!");
    }
}
class MarryCompany implements Marry{

    Person person;

    public MarryCompany(Person person) {
        this.person = person;
    }
    @Override
    public void marry() {
        before();
        person.marry();
        after();
    }
    public void before(){
        System.out.println("婚庆人员在布置现场");
    }
    public void after(){
        System.out.println("婚礼结束了,打钱");
    }
}

标签:void,System,线程,println,new,public
From: https://www.cnblogs.com/shisi2001/p/18282735

相关文章

  • IO线程-同步、互斥、条件变量
    1.同步1.1概念同步(synchronization)指的是多个任务(线程)按照约定的顺序相互配合完成一件事情(异步:异步则反之,并非一定需要一件事做完再做另一件事。)1.2同步机制通过信号量实现线程间同步。信号量:通过信号量实现同步操作;由信号量来决定线程是继续运行还是阻塞等待.信......
  • 【Java基础】--线程(包含面试题)
    本章主要了解什么是进程?进程和线程有什么关系?有什么区别?以及创建线程的方式有哪些?1.什么是进程?简单的来说,进程是指在系统中正在运行的一个应用程序,每个进程之间是独立的,每个进程均运行在其专用的且受保护的内存。2.什么是线程?线程,又称轻量级进程(LightWeightProcess)。......
  • springboot线程池简单配置
    @ConfigurationpublicclassThirdPartyOilSmallTaskConfig{@Bean("thirdPartyOilSmallTaskExecutor")publicThreadPoolTaskExecutoruniteOilThreadPoolTaskExecutor(){ThreadPoolTaskExecutorexecutor=newThreadPoolTaskExecutor();......
  • go当中的线程存储与使用
    1、settls从引导代码中可以看到,在执行settls前将m.tls放入了DI。go/src/runtime/asm_amd64.s:159TEXTruntime·rt0_go(SB),NOSPLIT|NOFRAME|TOPFRAME,$0....LEAQruntime·m0+m_tls(SB),DICALLruntime·settls(SB)....tls定义是无符号整形指针ty......
  • Winform SynchronizationContext多线程更新画面控件
    SynchronizationContext在通讯中充当传输者的角色,实现功能就是一个线程和另外一个线程的通讯。需要注意的是,不是每个线程都附加SynchronizationContext这个对象,只有UI线程是一直拥有的。故获取SynchronizationContext也只能在UI线程上进行SynchronizationContextcontex......
  • 深入理解Java线程池:从理论到实践
    Java线程池是现代软件开发中不可或缺的一部分,尤其在高并发场景下,合理使用线程池可以显著提升系统的响应能力和资源利用率。一、线程池的基础概念与重要性1.1线程池是什么?线程池是一种设计模式,用于管理和复用一组预创建的线程,以减少线程创建和销毁的开销,提高程序的性能和响......
  • Linux多进程和多线程(一)-进程的概念和创建
    进程进程的概念进程的特点如下进程和程序的区别LINUX进程管理getpid()getppid()进程的地址空间虚拟地址和物理地址进程状态管理进程相关命令pstoppstreekill进程的创建并发和并行fork()父子进程执行不同的任务创建多个进程进程的退出exit()和_exit()exit()函数......
  • C#线程锁
    namespaceConsoleApp5{internalclassProgram{publicstaticintindex;staticvoidMain(string[]args){for(inti=0;i<5;i++){Threadthread=newThread(FuncThread);......
  • Java基础——线程
    在当今的软件开发中,多线程技术是提升程序性能、实现并发处理的关键所在。Java作为一款广泛应用的编程语言,其内置的多线程支持为开发者提供了强大的工具箱。本文将深入探讨Java中的线程概念,包括线程的创建、生命周期、同步机制以及一些常见的问题和解决方案。1.线程的基本概念......
  • 【CUDA】 由GPGPU控制核心架构考虑CUDA编程中线程块的分配
    GPGPU架构特点由于典型的GPGPU只有小的流缓存,因此一个存储器和纹理读取请求通常需要经历全局存储器的访问延迟加上互连和缓冲延迟,可能高达数百个时钟周期。与CPU通过巨大的工作集缓存而降低延迟不同,GPU硬件多线程提供了数以千计的并行独立线程,这些线程可以在一个多处理器内部......