java中的多线程

计算机上正在运行的程序就是一个进程,而每个进程可以拥有多个线程,每个线程是进程的一个执行场景/执行单元。

进程与进程之间是不共享资源的,线程和线程之间会共享堆、方法区,但是每个线程会有其对应的栈空间。线程的栈空间存放线程执行的时需要用到的东西,例如在run一个程序时,jvm会run这个程序的main方法,main方法中我们可能会定义一个变量,此时这个变量是一个临时变量,而这个变量会被存放在栈中,还有栈中可能会调用方法,这个方法如果是递归方法,那么这些方法会依次压入栈中,当程序运行结束,这个栈的内存就会被释放掉。

以上是我学习线程概念时的逻辑,我的逻辑思维是否有什么问题呢?
如果有问题,是什么导致的盲区?
如果没有,我有什么盲区是我没有发现的?
答:为什么没有疑问java中线程是怎么起作用的?
线程又怎么使用?java包中是怎么封装线程的?

缺:什么是多线程呢?
当一个计算机是多核的,就代表这个计算机是可以真正多线程的。
当一个计算机是单核的,那么处理器可以依靠快速的运算能力切换线程运行,这个时候给我们的感觉就是这个机器是多线程的。

线程的实现
线程的实现可以有3种方式:
第一种:
创建一个类,extends Thread ,即继承线程类,然后重写run方法,run方法必须重写。然后在main方法中new一个Thread对象,调用start方法,这个start方法会创建一个独立的栈空间,用来运行这个新建的类的run方法,注意这个run方法的调用是分支线程创建出来之后由线程自己调用的,不用程序员关心,类似主线程的main方法,start方法在开辟出一个栈空间之后就完成了使命,此时会接着运行main方法体里的代码,同时又运行了另一个类中的run方法体,这就实现了多线程。
第二种:
创建一个类,implements Runnable,要实现run方法。逻辑同上。
然后new这个类,当new Thread时将这个类的对象作为参数传入。
再用Thread对象调用start。
第三种:
匿名内部类。
这块发现了一些问题,我们看一下匿名内部类的编写方式;

Thread t = new Thread(new Runnable(){
	public void run(){
		for (;i<100;i++ ) {
            System.out.println("my thread  " + i + "  is running");
        }
	}
})

可以看到匿名内部类的编写是new了一个接口,那么我们知道接口是不可以new一个对象的,这里偶然看到一个人是这么理解的:因为是匿名内部类,所以这个new 是new的一个类,Runnable是这个匿名类实现的接口,那么可以完整的理解为new class implements Runnable(){}。这种理解让我眼前一亮。

在控制台上我们看到run方法和main方法的输出会交互输出,并且频率不一,这是因为控制台只有一个,而且跟时间片、执行权有关?
答:这里需要了解一下线程的生命周期。线程的生命周期中共有5个状态,分别是新建状态、就绪状态、运行状态、阻塞状态、死亡状态。新建状态调用start方法然后转为就绪状态,run方法执行的时候为运行状态,当运行过程中有其他时间发生,例如执行sleep方法、输入数据等这时候线程会进入阻塞状态,将所占有的资源释放,等到执行完这些命令之后进入就绪状态继续等待时间片的分配,得到新的时间片之后继续执行剩下的run方法,run方法执行完后变成死亡状态。

Timer类:
定时器类
用于定时去执行一个线程
通过对象调用schedule方法,传三个参数
TimerTask对象参数:创建TimerTask对象时需要编写run方法,这个run方法就是定时任务需要执行的内容。
Date对象参数:给定时任务一个第一次执行时间,格式为格林威治时间。
毫秒数:period,一段时间;传一个毫秒数,表示每隔多少毫秒就执行一次定时任务。

FutureTask:
线程的第三种实现方式
在创建该对象时需要实现一个call方法,带对象类型返回值。
要获得这个值需要将FutureTask对象作为参数传给Thread,然后通过FutureTask对象调用get方法来获得这个返回值。

  FutureTask ft = new FutureTask(new Callable() {
            @Override
            public Object call() throws Exception {
                return 1 + 2;
            }
        });
        Thread t = new Thread(ft);
        t.start();
        try {
            Object obj = ft.get();
            System.out.println(obj);
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (ExecutionException e) {
            e.printStackTrace();
        }

需要注意的是如果缺少t.start()方法启动线程的话,这个返回值不会输出。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
Java线程实现的原理主要是通过线程对象的创建和启动来实现的。Java实现多线程的方式有四种:继承Thread类、实现Runnable接口、实现Callable接口、使用线程池。下面分别介绍这四种方式的实现原理: 1. 继承Thread类 继承Thread类是实现多线程的一种方式,它的实现原理是创建一个继承自Thread类的子类,并重写run()方法,在run()方法编写线程执行的代码。然后创建该子类的对象,并调用start()方法启动线程。 2. 实现Runnable接口 实现Runnable接口是实现多线程的另一种方式,它的实现原理是创建一个实现了Runnable接口的类,并实现run()方法,在run()方法编写线程执行的代码。然后创建该类的对象,并将其作为参数传递给Thread类的构造方法,最后调用start()方法启动线程。 3. 实现Callable接口 实现Callable接口是实现多线程的一种方式,它的实现原理是创建一个实现了Callable接口的类,并实现call()方法,在call()方法编写线程执行的代码。然后创建该类的对象,并将其作为参数传递给FutureTask类的构造方法,最后调用start()方法启动线程。 4. 使用线程池 使用线程池是实现多线程的一种方式,它的实现原理是创建一个线程池对象,并将任务提交给线程池执行。线程池会自动管理线程的创建和销毁,从而避免了频繁创建和销毁线程的开销。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值