多线程
并发和并行
并发:指两个或者多个事件在同一时间段内发生
在操作系统中,安装了多个程序,并发指的是在一段时间内宏观上有多个程序同时运行,这在单CPU系统中,每个时刻只能有一道程序执行,即微观上这些程序是分时的交替运行,只不过给人的感觉是同时运行的,那是因为交替运行的时间非常短的
当系统只有一个CPU时,线程会以某种顺序执行多个程序,这种情况称为线程的调度
并行:指两个或多个事件在同一时间发生(同时发生)
而在多个CPU系统中,则这些可以并发执行的程序便可以分配到多个处理器上(CPU),实现多任务并行执行,即利用每个处理器来处理一个可以并发执行的程序,这样多个程序便可以同时执行。
进程与线程
进程:是指一个内存中运行的应用程序,每个进程都有一个独立的内存空间,一个应用程序可以同时运行多个进程,进程也是程序的一个执行过程,是系统运行程序的基本单位,系统运行一个程序即是一个进程从创建,运行到消亡的过程
线程:线程是进程中的一个执行单元,负责当前进程中程序的执行,一个进程中至少有一个线程。一个进程中可以是有多个线程的,这个应用程序称为多线程程序。
线程调度
- 分时调度:所有线程轮流使用CPU的使用权,平均分配每个线程占用CPU的时间
- 抢占式调度:优先让优先级高的线程使用CPU,如果线程的优先级相同那么随机选择一个(线程随机性),Java使用的为抢占式调度。
创建线程类
Java使用java.lang.Thread类代表线程,所有的线程对象都必须是Thread类或其子类的实例。每个线程的作用是完成一定的任务,实际上就是执行一段程序流即一段顺序执行的代码。Java使用线程执行体来代表这段程序流。
Java通过继承Thread类来创建并启动多线程
package com.review;
public class ThreadDemo {
public static void main(String[] args) {
MyThread myThread=new MyThread("新的线程");
myThread.setPriority(9);
myThread.start();
for (int i = 0; i <1000 ; i++) {
System.out.println("main线程"+i);
}
}
}
class MyThread extends Thread{
public MyThread(String name){
super(name);
}
@Override
public void run() {
for (int i = 0; i <1000 ; i++) {
System.out.println(getName()+":正在执行"+i);
}
}
}
多线程执行时,在栈内存中,其实每一个执行线程都有一个执行线程都有一片自己属于的栈内存空间,进行方法的压栈和弹栈。当执行线程的任务结束了,线程自动在栈内存中释放了。但是当所有的执行线程都结束了,那么进程就结束了。
Thread类
构造方法:
public Thread():分配一个新的线程对象
public Thread(String name):分配一个指定名字的新的线程对象
public Thread(Runnable target):分配一个带有指定目标新的线程对象
public Thread(Runnable target, String name):分配一个带有指定目标新的线程对象并指定名字
常用方法:
public String getName():获取当前线程的名称
public void start():导致此线程开始执行,Java虚拟机调用此线程的run()方法
public void run():此线程要执行的任务在此处定义代码
public static void sleep(long millis):使当前正在执行的线程以指定的毫秒数暂停(暂时停止执行)
public static Thread currentThread():返回对当前正在执行的线程对象的引用
通过实现Runnable接口来创建多线程
package com.review;
public class RunnableDemo {
public static void main(String[] args) {
MyRunnable runnable=new MyRunnable();
Thread thread=new Thread(runnable,"小强");
thread.start();
for (int i = 0; i <20 ; i++) {
System.out.println(Thread.currentThread().getName()+" "+i);
}
}
}
class MyRunnable implements Runnable{
@Override
public void run() {
for (int i = 0; i <20 ; i++) {
System.out.println(Thread.currentThread().getName()+" "+i);
}
}
}
Thread类和Runnable接口的区别
如果一个类继承Thread,则不适合资源共享。但是如果实现了Runnable接口的话,则很容易的实现资源共享。
总结:
实现Runnable接口比继承Thread类所具有的优势
- 适合多个相同的程序代码的线程去共享一个资源
- 可以避免Java中的单继承的局限性
- 增加程序的健壮性,实现解耦操作,代码可以被多个线程共享,代码和线程独立
- 线程池只能放入实现Runnable线程,不能直接放入继承Thread的类
匿名内部类方式实现线程的创建
package com.review;
public class InnerClassRunnableDemo {
public static void main(String[] args) {
Runnable runnable=new Runnable() {
@Override
public void run() {
for (int i = 0; i <10 ; i++) {
System.out.println(Thread.currentThread().getName()+" "+i);
}
}
};
Thread myThread=new Thread(runnable,"小强");
myThread.start();
for (int i = 0; i <10 ; i++) {
System.out.println(Thread.currentThread().getName()+" "+i);
}
}
}