Java多线程-基础概述及基本建立方法

线程是程序的执行单元,允许多个任务在同一进程中并行执行。Java中可通过继承Thread类或实现Runnable接口创建线程。线程带来了CPU资源的充分利用和简化编程模型的优点,但也存在额外开销和并发控制问题。文章列举了创建线程的三种方式,并通过抢票和龟兔赛跑案例说明线程同步的重要性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

线程概述:

        线程是程序运行的基本执行单元。

        一个进程可以有一个或多个线程。进程与进程之间不共享内存,而一个进程中的线程可以共享系统派给这个进程的内存空间。进程是系统分配资源的单位,线程是CPU调度和执行的单位。

核心概念:

        1:任何一个Java程序都必须有一个主线程。一般这个主线程的名字为main()。只有在程序中建立另外的线程才能算是真正的多线程程序。也就是说一个程序必须拥有一个以上的线程。

        2:线程会带来额外的开销,如CPU调度时间,并发控制开销。

        3:对同一份资源进行操作时,会存在资源抢夺的问题,需要加入并发控制。

        4:每个线程在自己的工作内存交互,内存控制不当会造成数据不统一。

线程的意义:

        1:充分利用CPU资源 。

        2:简化编程模型 。

        3:简化异步事件处理。

        4:使GUI更有效率 。

        5:提高程序的执行效率。

 

建立线程的三种方法:

        1:继承Thread类

        Thread类的八个构造方法:

    public Thread();
    public Thread(Runnable target);
    public Thread(String name);
    public Thread(Runnable target,String name);
    public Thread(ThreadGroup group,Runnable target);
    public Thread(ThreadGroup group,String name);
    public Thread(ThreadGroup group,Runnable target,String name);
    public Thread(ThreadGroup group,Runnable target,String name,long stackSize);
	/*Runnable target:实现了Runnable接口的实例。
	  String name:线程的名字,此名字可以建立Thread实例后通过Thread类的setName方法设置。如果不设置线程名,就会使用默认线程名:Thread-N,N是线程建立的顺序,是一个不重复整数。
	  ThreadGroup group:当前建立的线程的线程组。如果不建立将会加到一个默认的线程组。
	  long stackSize:线程栈的大小,这个值一般是CPU页面的整数倍
	*/

        Thread类里常用的几个方法:

Thread.currentThread();//方法:是Thread类的静态方法,返回当前正在执行的线程对象
Thread.setName();//方法:为当前Thread对象设置名字
Thread.getName();//方法:得到当前Thread对象的名字
Thread.sleep(target);//方法:使当前线程睡眠target毫秒

        线程执行函数:Thread里的run()方法。

        建立线程函数:Thread里的start()方法。相当于调用Windows的建立线程函数CreateThread()。当start()方法调用成功(进入就绪状态),会自动调用run()方法。

        示例代码:

public class TestThread  extends Thread{
    public static void main(String[] args) {
        //创建一个线程对象
        TestThread testThread=new TestThread();
        //待用start()方法开启线程
        testThread.start();//线程开启不一定立即执行,而等待cpu调度

    }

    @Override
    public void run() {
        for (int i = 0; i < 20; i++) {
            System.out.println("wzkdm");
        }
    }
}

        2:实现Runnable接口

        Runnable接口:标识一个Java类是否可作为线程类,此接口只有一个抽象方法run()。所以一个线程类的唯一标识就是这个类是否实现了Runnable接口的run()方法。

        一般使用实现Runnable接口的方法,因为可以实现多个接口,而继承只能单继承。空出继承位可以留给更需要继承的类而不是Thread类。

        使用Runnable接口创建线程步骤:

                1:将实现Runnable接口实例化。 ​

                2:建立一个Thread对象,并将第一步实例化后的对象作为参数传入Thread类的构造方法,最后通过Thread类的start()方法建立。

public class TestThread2  implements Runnable{
    public static void main(String[] args) {
        //创建一个线程对象
        TestThread2 testThread=new TestThread2();
        //通过线程对象来开启线程,代理
        new Thread(testThread).start();//线程开启不一定立即执行,而等待cpu调度
    }

    @Override
    public void run() {
        System.out.println("song");
    }
}

      通过两个案例来进一步了解多线程:

        1:抢票案例:

        主程序:

//问题:多个线程操作同一个资源的情况下,线程不安全,数据会紊乱
public class TestThread3{
    public static void main(String[] args) {
        BuyTicket ticket = new BuyTicket();

        new Thread(ticket, "song1").start();
        new Thread(ticket, "song2").start();
        new Thread(ticket, "song3").start();
        new Thread(ticket, "song4").start();
    }
}

         买票类:

public class BuyTicket implements Runnable{

    private int ticketNums=10;
    boolean flag=true;

    @Override
    public void run() {
        while (flag){
            buy();
        }
    }

    private void buy(){
        if(ticketNums<=0){
            flag=false;
            return;
        }
        //模拟延时
        try {
            Thread.sleep(300);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        System.out.println(Thread.currentThread().getName()+"-->拿到了第"+ticketNums--+"张票");
    }
}

        2:龟兔赛跑案例:

public class Race  implements Runnable{

    public static void main(String[] args) {
        Race race=new Race();
        new Thread(race,"兔子").start();
        new Thread(race,"乌龟").start();
    }
    //静态变量胜利者
    private static String winner;

    @Override
    public void run() {
        for (int i = 1; i <=100; i++) {
            //模拟兔子休息
            if(Thread.currentThread().getName().equals("兔子")&&i%10==0){
                try {
                    Thread.sleep(1);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }

            //判断比赛是否结束
            boolean flag=gameOver(i);
            //如果比赛结束就停止程序
            if (flag){
                break;
            }
            System.out.println(Thread.currentThread().getName()+"--->跑了"+i+"步");
        }
    }
    //判断是否完成比赛
    private boolean gameOver(int steps){
        //判断是否有胜利者
        if(winner!=null){
            return true;
        }else {
            if(steps==100){
                winner=Thread.currentThread().getName();
                System.out.println("winner is"+winner);
                return true;
            }
        }
        return false;
    }
}

        3:实现Callable接口

                Callable接口是可以让线程返回值的,和线程池一起使用,常规创建线程的方法是实现Runnable接口。

    //①:需要返回值类型

​	//②:重写call方法(就不是run方法了),需要抛出异常

​	//③:创建目标对象

​	//④:创建执行服务:

    ExecutorService ser=Executor.newFixedThreadPool(1);//1指的是线程池大小

​	//⑤:提交执行:

    Future<Boolean> result1=ser.submit(t1);

​	//⑥:获取结果:

    Boolean r1=result1.get();

​	//⑦:关闭服务:

    ser.shutdownNow();

 

静态代理模式(多线程的设计模式):

        静态代理:由程序员创建或特定工具自动生成源代码,也就是在编译时就已经将接口、真实对象类、代理对象类等确定下来。
        1:真实对象和代理对象实现同一个接口。
        2:代理对象要代理真实角色。
        3:代理对象可以做很多真实对象做不了的事情。
        4:真实对象专注于做自己的事情。

        通过结婚案例了解多线程的设计模式

        主程序:

public class StaticProxy {
    public static void main(String[] args) {
        //wddingCompany类接收一个you对象,调用HappMarry方法。
        new WeddingCompany(new You()).HappMarry();
    }
}

        同时实现的接口:

public interface Marry{
    void HappMarry();
}

        真实对象:

//你,主角
public class You implements Marry{

    @Override
    public void HappMarry(){
        System.out.println("song要结婚了,好开心");
    }
}

        代理对象:

//婚庆公司,代理
public class WeddingCompany implements Marry{

    private Marry target;

    public WeddingCompany(Marry target){
        this.target=target;
    }

    @Override
    public void HappMarry() {
        before();
        this.target.HappMarry();
        after();
    }

    private void before(){
        System.out.println("结婚之前,布置现场");
    }

    private void after(){
        System.out.println("结婚之后,收拾现场");
    }

}

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值