线程和进程的区别: 一个进程内可以有多个线程,线程是比进程更小的单位
1、 进程是系统分配资源的基本单位,线程是CPU调度的基本单位,进程是程序的一次执行,线程是CPU调度的一次执行
2、进程之间是相互独立的,每个进程拥有自己的一块自身内存区域(进程间的通信是需要解决的问题),而多个线程之间是共享一块内存区域和一组资源的,有可能相互影响(因此会产生多个线程同时访问某一块数据的时候会导致数据不一致的问题,因此线程之间的同步是很重要的一件事情)
3、 线程基本上不拥有资源,只拥有一点在运行中必不可少的资源(寄存器,栈,程序计数器),所以线程的切换要比进程切换的负担小,但是它可与同一个进程的其他线程共享进程所拥有的全部资源
4、一个线程可以创建和撤消另一个线程,同一个进程中的多线程之间可以并发执行,但是线程是程序内部的顺序控制流,本身不能运行,它只能用于程序之中,使用分配给程序的内存资源和环境。
进程:执行中的程序(程序是静态的概念,进程是动态的概念)
多线程: 是指在单个程序中可以同时运行多个不同的线程,执行不同的任务。
多线程编程的目的: 就是最大限度的利用CPU资源,当某一线程的资源只需要I/O而不需要CPU资源的时候,可以先放弃CPU的占用让需要CPU资源的其他线程使用。
单线程: 当程序启动时,就会自动产生一个线程,主方法main就是在这个主线程上运行。
线程中的重点: 线程的生命周期,线程的实现,多线程的同步
多线程:一个程序实现多个代码同时交替运行就需要产生多个线程,
CPU随机的抽取时间,让我们的线程一会儿做这件事情,一会做另外一件事情
和其他语言不同,java内置支持多线程编程,每个线程都有独立的执行路径,因此多线程是多任务处理的一种特殊形式
多任务处理被所有的现代操作系统所支持,然而,多任务处理器有两种截然不同的类型:基于进程的和基于线程的
进程需要分配给独立的地址空间,进程间的通信是昂贵的受限的,进程间的转换也是很需要花费时间的,另一方面线程共享相同的地址空间并且共同分享一个进程,线程间的切换成本低,通信方便。
Java中两种实现线程的方式:
第一:继承Thread类,并重写Run方法
第二:通过定义实现Runnable接口的类而实现Run方法
strart() 你要是想启动线程类,只有唯一的一个办法,使用start()方法来启动线程,然后该方法会自动调用 run()方法。start方法首先为线程的执行准备好系统资源,然后再去调用 run 方法。当某个类继承了Thread类之后,该类就叫做一个线程类。
run() :把你想要并行执行的代码块放在run方法中
多个线程一旦启动了,就不再受你控制了,这完全是你的CPU和操作系统自己决定的
双核的CPU最多只能有两个线程在执行,单核的CPU是某一时刻只能执行一个线程,但是如果你定义了两个线程,这两个线程的执行顺序你也是无法确定的。
对于单核 CPU 来说,某一时刻只能有一个线程在执行(微观串行) ,从宏观角度来看,多个线程在同时执行(宏观并行) 。
对于双核或双核以上的 CPU来说,可以真正做到微观并行。
public class ThreadTest {
public static void main(String[] args) {
Thread1 t1 = new Thread1();
Thread2 t2 = new Thread2();
// 通过调用start方法启动了两个线程, start是启动线程的唯一方法
t1.start();
t2.start();
// 直接调用run方法,跟线程没啥关系,跟直接调用一个类的成员方法相似
t1.run();
t2.run();
}
}
class Thread1 extends Thread{
@Override
public void run(){
for(int i = 0; i<10; i++){
System.out.println("hello " + i);
}
}
}
class Thread2 extends Thread{
@Override
public void run(){
for(int i = 0; i<10; i++){
System.out.println("world " + i);
}
}
}
第二:通过定义实现Runnable接口的类而实现Run方法
public class RunnableTest {
public static void main(String[] args) {
Thread t1 = new Thread(new Runnable1());
Thread t2 = new Thread(new Runnable2());
// 通过调用start方法启动了两个线程, start是启动线程的唯一方法
t1.start();
t2.start();
// 因为Runnable接口中只有一个run方法,所以也可以采用匿名内部类的方法
Thread t3 = new Thread(new Runnable(){
public void run() {
for (int i = 0; i < 10; i++) {
System.out.println("helloworld " + i);
}
}
});
t3.start();
}
}
class Runnable1 implements Runnable {
@Override
public void run() {
for (int i = 0; i < 10; i++) {
System.out.println("hello " + i);
}
}
}
class Runnable2 implements Runnable {
@Override
public void run() {
for (int i = 0; i < 10; i++) {
System.out.println("world " + i);
}
}
}