文章目录
前言
进程间的通信较为复杂,比如不同计算机的进程通信需要通过网络协议等方式。
并行指的是计算机同时运行多个任务的能力,并发指的是计算机同时应对多个任务的能力
IO操作不会占用CPU,但是使用阻塞IO,该线程就在进行IO操作的时候进入阻塞状态,没有充分利用线程
1. 创建线程
三种基础创建线程的方式:
基础方法
Thread t=new Thread(){
@Override
public void run() {
System.out.println("线程运行");
}
};
t.setName("wuhu");
t.start();
基础方法简化(lambda)
new Thread(()->{
System.out.println("线程运行");
}).start();
使用Runnable参数代表线程需要执行的任务
将Thread和Runnable的初始化分隔开(注意:Runnable接口的注释为functionalInterface,该注释表示Runnable参数代表一个可运行的任务(即方法),所以我们可以看到很多方法中需要的参数类都有该注释,代表调用这个方法传参时,传一个方法就行了!比如Thread t2 =new Thread(run)这个run参数可以直接传一个方法,一般使用lambda表达式传参更方便)
Runnable run=new Runnable() {
@Override
public void run() {
System.out.println("线程2运行");
}
};
Thread t2=new Thread(run);
t2.start();
4、 使用lambda函数简化Runnable的初始化,方法参数可以分为以下几类:
private static <T> void demo(
Supplier<T> arraySupplier,
Function<T,Integer> lengthFun,
BiConsumer<T,Integer> put Consumer,
Consumer<T> printConsumer)
Runnable run3=()->{
System.out.println("线程3运行");
};
Thread t3=new Thread(run3);
t3.start();
5、 FutureTask创建,FutureTask实现了Runnable接口,所以其也可以作为参数传入Thread构造方法,且其可以用于获得其中call(类似于run方法)方法的返回值,其中get方法类似于join方法,可以使调用该方法的线程阻塞在这一行代码,等待futureTask的返回值。
FutureTask<Integer> futureTask=new FutureTask<>(new Callable<Integer>() {
@Override
public Integer call() throws Exception {
return 1;
}
});
Thread t =new Thread(futureTask);
t.start();
int res=futureTask.get();
2. Runnable和Thread创建线程原理
Thread类中封装了run方法和Runable类的成员变量target,若不使用Runnable类去初始化线程,则运行重写的run方法,如果有把runnable类初始化并传入Thread的构造方法内(给target成员变量赋值),那么就优先执行target.run()。
3.Windows和Linux查看JAVA进程
Jps可以查看和java相关的进程
4. 线程方法
只调用run方法 不调用start方法,run方法中的语句会被执行,但不会创建新的线程来执行run方法。
同一个线程的Start方法不能多次调用
4.1 Sleep
Sleep方法执行时,该线程会将时间片让给其他线程,该线程进入TIMEED WATIING状态。该方法能被interrupt打断,打断后会抛出InterruptedException异常。
Yield方法执行时,该线程同样会将时间片让出来,但是进入Runnable状态,该状态代表就算让出时间片的下一刻,该线程同样能够参与到获取时间片的竞争当中。
4.2优先级
可以同个setPriority方法来设置优先级,当CPU比较空闲的时候,优先级没啥用,因为每个线程都能很好地获得时间片,且它仅仅是一个标签而不是规则,调度器完全可以无视它按照自己的规则进行线程调度。
4.3Join方法
异步指不需要等待其他线程返回,同步只需要等待其他线程返回
Join(1000)这个1000代表线程最多等待多少时间,如果超过则不等待该线程返回
4.4 Interrupt方法
可以打断wait,join,sleep,Locksupport.park的线程,也可以打断正在运行的线程(该线程不会结束运行),被打断的线程的标记isInterrupted成员变量会被设置为true(可以通过该成员变量来停止线程的运行,使用Thread.currentThread().isInterrupted查看该成员变量;当为true时,Locksupport.park方法会失效),但是打断wait,join和sleep状态下的线程时,该标记会被置为false。
4.5守护线程
t.setDaemon(true)将线程设置为守护线程,当主线程结束时,不管t线程是否运行结束,都必须结束(垃圾回收就是守护线程)。
4.6线程状态
操作系统层面的五种状态:
1、初始状态(NEW):线程刚刚创建的状态
2、可运行状态(RUNABLE):即该线程随时准备获得时间片进行运行
3、阻塞状态(BLOCK):该状态的线程不会有机会获得时间片,且被唤醒后也只是回到RUNNABLE状态
4、运行状态(RUNNING)
5、终止状态(TERMINATED):该线程生命周期结束
JAVA API层面的六种状态
RUNNABLE包含阻塞,运行和可运行三种状态,灰色部分都代表阻塞状态。