并行和并发即相似又有区别的(微观概念)
并行:指两个或多个事件在同一时刻点发生;
并发:指两个或多个事件在同一时间段内发生。(单核CPU系统情况)
线程同步和异步的区别:
同步:就是指一个线程要等待上一个线程执行完之后才开始执行当前的线程,它们都同时操作一个数据,这时需要对数据进行保护,这个保护就是线程同步。
异步:是指一个线程去执行,它的下一个线程不必等待它执行完就开始执行,这两个线程没有什么关系,都可以各干各的。
多进程和多线程:
多进程:操作系统中同时运行多个程序;
多线程:在同个进程中同时运行多个任务。
进程和线程的区别:
进程:有独立的内存空间,进程中的数据存放空间(堆空间和栈空间)是独立的,至少有一个线程;
线程:堆空间是共享的,栈空间是独立的,线程消耗的资源也比进程小,相互之间可以影响,又称为轻型进程或进程无。
Java程序的进程里至少包含主线程和垃圾回收线程(后台线程)
因为一个进程中的多个线程是并发运行的,那么从微观角度上考虑也是有先后顺序的,那么哪个线程执行完全取决于CPU调度器(JVM来调度)程序员是控制不了的。
线程调度:
计算机通常只有一个CPU时,在任意时刻只能执行一条计算机指令,每个进程只有获得CPU的使用权才能执行指令。所谓多进程并发运行,从宏观上看其实是各个进程轮流获得CPU的使用权,分别执行各自的任务。那么,在可运行池中,会有多个线程处于就绪状态等待CPU,JVM就负责线程的调度。
JVM采用的是抢占式调度,没有采用分时调度,因此会造成多线程执行结果的随机性。
多线程的优势:
多线程作为一种多任务、并发的工作方式,当然有其存在的优势:
1) 进程之间不能共享内存,而线程之间可以共享内存(堆内存);
2) 系统创建进程时需要为该进程重新分配系统资源。创建线程则代价小很多,因此实现多任务并发时,多线程效率更高。
3) Java语言本身内置多线程功能的支持,而不是单纯的作为底层系统的调度方式,从而简化了多线程。
Java操作进程:
在Java中如何去运行一个进程:
方式1:Runtime类的exec()方法;
Runtime runtime =Runtime.getRuntime();
runtime.exec(“notepad”);
方式2:ProcessBuilder类的start()方法;
ProcessBuilder pd = newProcessBuilder(“notepad”);
pd. start();
创建并启动线程:
方式1:继承Thread类
步骤:
1、定义一个类A继承于java.lang.Thread类;
2、在A类中覆盖Thread类中的run方法;
3、我们在run方法中编写需要执行的操作àrun方法里面的,线程执行体;
4、 在mian方法(线程)中,创建线程对象,并启动线程。
创建线程类: A类 a = new A类();
调用线程对象的start()方法: a.start();//启动一个线程
代码的实现:
//播放音乐的线程
class MusicThread extends Thread{
@Override
public void run() {
for (int i = 0; i < 50; i++) {
System.out.println("播放音乐" + i);
}
}
}
//方式1:继承Thread类
public class ExtendsThreadDemo {
public static void main(String[] args) {
//主线程:运行游戏
for (int i = 0; i < 50; i++) {
System.out.println("打游戏"+i);
if(i==10){
//创建对象,并启动线程
MusicThread music = new MusicThread();
music.start();//启动一个新的线程,不能调用run方法
}
}
}
}
方式2:实现Runnable接口
1、定义一个A类实现于java.lang.Runnable接口,注意A类不是线程类;
2、在A类中覆盖Runnable接口中的run方法;
3、我们在run方法中编写需要执行的操作àrun方法里面的,线程执行体;
4、在main方法(线程)中,创建线程对象,并启动线程。
创建线程类对象: Thread t = new Thread(newA());
调用编程对象的start()方法: t.start();
代码的实现:
//播放音乐的线程类
class MusicRunnableImpl implements java.lang.Runnable{
@Override
public void run() {
for (int i = 0; i < 50; i++) {
System.out.println("播放音乐"+i);
}
}
}
//方式2:实现Runnable接口
public class ImplementsRunnableDemo {
public static void main(String[] args) {
//主线程:运行游戏
for (int i = 0; i < 50; i++) {
System.out.println("打游戏"+i);
if(i==10){
//创建对象,并启动线程
Runnable target = new MusicRunnableImpl();
Thread thread = new Thread(target);
thread.start();
}
}
}
}
使用匿名内部类来创建线程;
只适用于某一个类只使用一次的情况。
//使用内部类来创建线程
//值适用于某一个类只使用一次的情况
public class AnonymousInnerClassDemo {
//方式1
public static void main(String[] args) {
// 主线程:运行游戏
for (int i = 0; i < 50; i++) {
System.out.println("打游戏" + i);
if (i == 10) {
// 创建对象,并启动线程
new Thread(new Runnable() {
@Override
public void run() {
for (int i = 0; i < 50; i++) {
System.out.println("播放音乐" + i);
}
}
}).start();
}
}
}
//方式2
private static void test1() {
// 主线程:运行游戏
for (int i = 0; i < 50; i++) {
System.out.println("打游戏" + i);
if (i == 10) {
// 创建对象,并启动线程
new Thread() {
@Override
public void run() {
for (int i = 0; i < 50; i++) {
System.out.println("播放音乐" + i);
}
}
}.start();
}
}
}
}
继承和实现的选择:
继承方式:(继承Thread类)
1) Java中类是单继承的,如果继承了Thread类,该类就不能再有其他直接父类;
2) 从操作上分析,继承方式更简单,获取线程名字也简单;(操作上更简单)
3) 从多线程共享同一个资源上分析,继承方式不能做到。
实现方式:(实现Runnable接口)
1) Java中类可以多实现接口,此时该类还可以继承其他类,还可以实现其他接口;
2) 从操作上分析,实现方式操作更复杂,得使用Thread.currentThread()来获取当前线程的引用
3) 从多线程共享同一资源上分析,实现方式可以做到。(是否共享同一资源)