java进程与线程知识_JAVA基础知识|进程与线程

一、什么是进程?什么是线程?

操作系统可以同时支持多个程序的运行,而一个程序可以狭义的认为就是一个进程。在一个进程的内部,可能包含多个顺序执行流,而每个执行流就对应一个线程。

1.1、进程

进程:是计算机中的程序关于某数据集合上的一次运行活动,是系统进行资源分配和调度的基本单位。当程序进入内存运行时,即为开启了一个进程。

进程的特点:

独立性:进程是系统中独立的实体,可以拥有独立的资源

动态性:进程是动态的,它有自己的生命周期

并发性:多个进程可以并发运行,互不影响

并发性和并行性是不同的概念:并行是指同一时刻,多个命令在多个处理器上同时执行;并发是指在同一时刻,只有一条命令是在处理器上执行的,但多个进程命令被快速轮换执行,使得在宏观上具有多个进程同时执行的效果。

1.2、线程

线程:是程序内部的顺序执行流。一个标准的线程由线程ID,当前指令指针(PC),寄存器集合和堆栈组成。线程并不拥有自己的系统资源,它与其他线程一起分享进程的系统资源。

【举例】

public classTest {public static voidmain(String[] args) {

Thread th=Thread.currentThread();

System.out.println("Tread name:" +th.getName());

method();

}public static voidmethod() {

Thread th=Thread.currentThread();

System.out.println("Tread name:" +th.getName());

}

}

执行结果:(当java程序启动的时候,会启动一个由主方法(public static void main(String[] args))所开启的主线程main)

Tread name:main

Tread name:main

执行过程如下:

f95c2e81ac018162a0ffdaa7cec65e87.png

程序的执行过程:首先把程序的代码放到内存的代码区里面,代码放到代码区后并没有马上开始执行,但这时候说明了一个进程准备开始,进程已经产生了,但还没有开始执行,平常所说的进程的执行指的是进程里面主线程开始执行了,也就是main()方法开始执行了,在我们机器里面实际上运行的都是线程。

线程状态:

43b7e1e3126c6f1beb0d1187782bc471.png

线程总共有5大状态

新建状态:新建线程对象,并没有调用start()方法之前

就绪状态:调用start()方法之后线程就进入就绪状态,在变为当前线程之前都是为就绪状态。值得一提的是,线程从阻塞状态中恢复的时候也会进入就绪状态

运行状态:线程被设置为当前线程,开始执行run()方法。就是线程进入运行状态

阻塞状态:线程被暂停,比如说调用sleep()方法后线程就进入阻塞状态

死亡状态:线程执行结束

二、如何创建多个线程?

2.1、继承Thread类

【举例】

public class MyThread extendsThread {privateString params;publicMyThread(String params) {this.params =params;

}

@Overridepublic voidrun() {

Thread thread=Thread.currentThread();

System.out.println(this.params + ":" +thread.getName());

}

}

public classTest {public static voidmain(String[] args) {

Thread th=Thread.currentThread();

System.out.println("main():" +th.getName());

threadTest1();

threadTest2();

method();

}public static voidthreadTest1() {

MyThread myThread= new MyThread("threadTest1");

myThread.start();

}public static voidthreadTest2() {

MyThread myThread= new MyThread("threadTest2");

myThread.run();

}public static voidmethod() {

Thread th=Thread.currentThread();

System.out.println("method():" +th.getName());

}

}

执行结果:

main():main

threadTest2:main

method():main

threadTest1:Thread-0

调用myThread.start()方法,会开启一个新的线程Thread-0。而调用run()方法时,不会开启一个新的线程,仍然是单线程模式。

2.2、实现Runnable接口

【举例】

public class MyThread implementsRunnable {privateString params;publicMyThread(String params) {this.params =params;

}

@Overridepublic voidrun() {

Thread thread=Thread.currentThread();

System.out.println(this.params + ":" +thread.getName());

}

}

public classTest {public static voidmain(String[] args) {

Thread th=Thread.currentThread();

System.out.println("main():" +th.getName());

threadTest1();

threadTest2();

method();

}public static voidthreadTest1() {

MyThread myThread= new MyThread("threadTest1()");//这种线程创建方式有很多弊端,使用Executors提供的线程池更好

myThread.run();

}public static voidthreadTest2() {

MyThread myThread= new MyThread("threadTest2()");

Thread thread= newThread(myThread);

thread.start();

}public static voidmethod() {

Thread th=Thread.currentThread();

System.out.println("method():" +th.getName());

}

}

执行结果:

main():main

threadTest1():main

method():main

threadTest2():Thread-0

实现Runnable接口和继承Thread类这两种开辟新线程的方法,应该优先选择实现Runnable接口。因为接口可以实现多个,而类只能是单继承。

2.3、实现Callable接口

实现Callable接口的好处在于可以获取到线程的返回值,关于Callable和Future,我们会在后面再详细的介绍。

【举例】

public class CallThread implements Callable{

@OverridepublicInteger call() {int i = 0;for (; i < 100; i++) {

Thread thread=Thread.currentThread();

System.out.println(i+ "\t" +thread.getName());

}returni;

}

}

public classTest {public static void main(String[] args) throwsExecutionException, InterruptedException {

CallThread callThread= newCallThread();

FutureTask ft = new FutureTask<>(callThread);

Thread thread= newThread(ft);//这种线程创建方式有很多弊端,使用Executors提供的线程池更好

thread.start();

System.out.println("返回值:" +ft.get());

System.out.println("===============");

Thread thread1=Thread.currentThread();

System.out.println("线程:" +thread1.getName());

}

}

执行结果:

0 Thread-0

1 Thread-0

2 Thread-0

3 Thread-0

4 Thread-0

5 Thread-0

6 Thread-0

7 Thread-0

8 Thread-0

9 Thread-0返回值:10

===============线程:main

虽然程序中打开了两个线程,但是由于需要获取到Thread-0线程的返回值(ft.get()),所以Thread-0线程和main线程并不能并发执行,只有当Thread-0线程执行结束,才可以继续执行main线程。

【修改】

public classTest {public static void main(String[] args) throwsExecutionException, InterruptedException {//CallThread callThread = new CallThread();//修改为lambda表达式

FutureTask ft = new FutureTask<>(()->{int i = 0;for (; i < 10; i++) {

Thread thread=Thread.currentThread();

System.out.println(i+ "\t" +thread.getName());

}returni;

});

Thread thread= newThread(ft);

thread.start();//System.out.println("返回值:" + ft.get());

System.out.println("===============");

Thread thread1=Thread.currentThread();

System.out.println("线程:" +thread1.getName());

}

}

执行结果:

===============

0 Thread-0

1 Thread-0

2 Thread-0

3 Thread-0

4 Thread-0

5 Thread-0

6 Thread-0

7 Thread-0线程:main8 Thread-0

9 Thread-0

当把“System.out.println("返回值:" + ft.get());”注释掉以后,两个线程就可以并发执行了。

2.4、Future设置超时时间

String result;

ExecutorService executor=Executors.newSingleThreadExecutor();

FutureTask future =

new FutureTask<>(new Callable() {public String call() throwsInterruptedException {

TimeUnit.SECONDS.sleep(4);return "ok";

}

});

executor.execute(future);//在这里可以做别的任何事情

try{

result= future.get(5000, TimeUnit.MILLISECONDS); //取得结果,同时设置超时执行时间为5秒。同样可以用future.get(),不设置执行超时时间取得结果。

System.out.println(result);

}catch(InterruptedException e) {

future.cancel(true);

}catch(ExecutionException e) {

future.cancel(true);

}catch(TimeoutException e) {

future.cancel(true);

}finally{

executor.shutdown();

}

设置超时时间,如果超过5秒还没有返回值,则抛出超时异常

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值