这是我参与11月更文挑战的第24天,活动详情查看:2021最后一次更文挑战」
线程与进程
程序,进程,线程的区别
-
程序:一段静态的代码
-
进程:正在运行的程序。有生命周期
- 系统会为进程分配资源
-
线程:进程可进一步细化为线程,是程序内部执行的一条执行路线
- 线程作为调度和执行的单位,每个线程拥有独立的运行栈和程序计数器
- 一个java程序运行至少有三个线程:main线程,gc(垃圾回收)线程,异常处理线程
有很多单独运行的程序,每个程序有一个独立的进程。
进程想要执行任务就需要依赖线程。换句话说,就是进程中的最小执行单位就是线程,并且一个进程中至少有一个线程。
java默认2个线程,1.main线程 2.gc线程
java是并行的,由一个CPU交替执行。由于速度太快,看不出来。
线程的方法
1.start() :启动一个线程,这时此线程处于就绪(可运行)状态,并没有运行。如果当前CPU空闲,就会执行run方法
2.run()方法中为线程需要执行的方法
3.getName:获取名称
4.join()
5.yield():礼让线程,释放自己CPU,但不会释放同步锁,进入就绪状态。 但是进入就绪状态后还是会去抢夺锁,可能又获得了锁
6.interrupt() :中断线程,修改中断标志位为true,
实现多线程的方法
1.继承Thread类
2.实现Runnbale接口
1.创建类实现Runnable接口
2.实现run方法
3.创建Thread,将该类塞入Thread的参数
public static void main(String[] args) {
new Thread(MyThread).start();
}
class MyThread implements Runnable{
@Ovrride
public void run(){
xxxxx
}
}
3.实现Callable接口
1.有返回值
2.可以抛出异常
3.实现call方法,而不是run方法
泛型的参数就是返回异常的类型
public interface Callable<V> {
/**
* Computes a result, or throws an exception if unable to do so.
*
* @return computed result
* @throws Exception if unable to compute a result
*/
V call() throws Exception;
}
选择String,那么call方法返回的类型就是String
public class myThread implements Callable<String> {
@Override
public String call() throws Exception {
// 实现代码
return "1";
}
}
那么怎么能够调用callabel呢?
new Thread().start 参数只能是Runnnable类型,那么想要多线程,Callable就需要和Runnable搭上关系。
通过FutureTask是Runnbale的实现类勾搭上Runnable,FutureTask可以接收Callable参数
public FutureTask(Callable<V> callable) {
if (callable == null)
throw new NullPointerException();
this.callable = callable;
this.state = NEW; // ensure visibility of callable
}
public static void main(String[] args) throws ExecutionException, InterruptedException {
// 这一个相当于Runnable ,将其放入Thread的参数
FutureTask< String > futureTask = new FutureTask<>(new myThread());
new Thread(futureTask,"A").start();
// 获取Callable的返回结果
String s = futureTask.get();
System.out.println(s);
}