进程与线程

进程与线程

进程与线程

1.进程(Process)是计算机中的程序关于某数据集合上的一次运行活动,是系统进行资源分配和调度的基本单位,是操作系统结构的基础。在早期面向进程设计的计算机结构中,进程是程序的基本执行实体;在当代面向线程设计的计算机结构中,进程是线程的容器。程序是指令、数据及其组织形式的描述,进程是程序的实体;

2.线程是在进程基础上划分的更小的程序单元,线程是在进程基础上创建并且使用的,所以线程依赖于进程的支持;线程的启动速度比进程快,所以使用多线程进行并发处理的时候,其执行的性能高于进程;

继承 Thread 类实现多线程

多线程要执行的功能都应该在 run() 方法中进行定义,但是 run() 方法不能直接被调用,要想启动多线程必须使用 start() 方法完成

package com.test;

class MyThread extends Thread { // 得到了一个线程主体类
    private String name ;
    public MyThread(String name) {  // 保存线程名称
        this.name = name ;
    }
    @Override
    public void run() {         // 覆写run()方法
        for (int x = 0 ; x < 5 ; x ++) {
            System.out.println("【"+this.name+" - 线程】运行,x = " + x);
        }
    }
}
public class JavaDemo {
    public static void main(String[] args) {
        MyThread threadA = new MyThread("线程A") ;
        MyThread threadB = new MyThread("线程B") ;
        MyThread threadC = new MyThread("线程C") ;
        threadA.start();    // 通过Thread类继承而来
        threadB.start();    // 通过Thread类继承而来
        threadC.start();    // 通过Thread类继承而来
    }
}

运行结果:
运行结果图

此时,虽然调用的是 start() 方法,但是执行的是 run() 方法

start() 方法的源代码

public synchronized void start() {
    if (threadStatus != 0) //判断线程状态
        throw new IllegalThreadStateException(); //抛出一个异常
    group.add(this);

    boolean started = false;
    try {
        start0();
        started = true;
    } finally {
        try {
            if (!started) {
                group.threadStartFailed(this);
            }
        } catch (Throwable ignore) {
        }
    }
}

private native void start0();
  1. 这时,会发现在 start() 方法中调用了 start0() 方法,而 start0() 方法只定义了方法名称,但是 start0() 方法使用了 native 进行了定义,表示此方法需要依赖于操作系统来实现
  2. 此时,会发现 start() 方法里面会抛出一个"IllegalThreadStateException"异常类的对象,但是程序没有使用 throws 或者是使用 try-catch 处理,所以该异常一定是 RuntimeException 的子类;
  3. 抛出该异常的条件:每一个线程类的对象只允许启动一次,若是重复启动,则会抛出 IllegalThreadStateException 异常

举个栗子

package com.test;

class MyThread extends Thread {
    private String name ;
    public MyThread(String name) { 
        this.name = name ;
    }
    @Override
    public void run() {     
        for (int x = 0 ; x < 5 ; x ++) {
            System.out.println("【"+this.name+" - 线程】运行,x = " + x);
        }
    }
}
public class JavaDemo {
    public static void main(String[] args) {
        MyThread threadA = new MyThread("线程A") ;
        threadA.start();//第一次启动
        threadA.start();//第二次启动
 
    }
}

运行结果:
运行结果图

Runnable 实现多线程

基于 Runnable 接口实现多线程

Module java.base
Package java.lang
Interface Runnable

接口定义

@FunctionalInterface
public interface Runnable {
void run();
}

但是,此时不再继承 Thread 父类了,那么对于此时的 MyThread 类中也就不再支持 start()方法,所以此时需要使用 Thread 的构造方法 public Thread​(Runnable target)
类方法详情

利用 Thread 的构造方法 public Thread​(Runnable target) 启动多线程

package com.test;

class MyThread implements Runnable {
    private String name ;
    public MyThread(String name) { 
        this.name = name ;
    }
    @Override
    public void run() {     
        for (int x = 0 ; x < 5 ; x ++) {
            System.out.println("【"+this.name+" - 线程】运行,x = " + x);
        }
    }
}
public class JavaDemo {
    public static void main(String[] args) {
        Thread threadA = new Thread(new MyThread("线程A")) ;
        Thread threadB = new Thread(new MyThread("线程B")) ;
        threadA.start();
        threadB.start();
 
    }
}

运行结果:
运行结果图
此时,由于程序只是实现了 Runnable 接口对象,而不是继承 Thread 父类,避免了线程主体类单继承的局限

Callable 实现多线程

接口定义

@FunctionalInterface
public interface Callable<V> {
	public V call() throws Exception;
}

此时,可以看到 Callable 接口定义的时候设置了一个泛型,并且此泛型的类型就是返回值的类型

关系图

基于 Callable 接口实现多线程

package com.test;

import java.util.concurrent.Callable;
import java.util.concurrent.FutureTask;

class MyThread implements Callable<String> {
	@Override
	public String call() throws Exception {
		for (int i = 0; i < 5; i++) {
			System.out.println("线程" + i + "执行中");
		}
		return "线程执行完毕";
	}
}
public class JavaDemo {
    public static void main(String[] args) throws Exception {
    	FutureTask<String> task = new FutureTask<>(new MyThread());
    	new Thread(task).start();
    	System.out.println(task.get());
    }
}

运行结果:
运行结果图

Runnable 与 Callable 的区别

  1. java.lang.Runnable接口只提供一个 run() 方法,并且无返回值,于JDK1.0提出
  2. java.util.concurrent.Callable 接口提供有 call() 方法,可以有返回值,于JDK1.5之后提出
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值