一、线程基本概念
线程中基础概念:
并发:两个或多个事件在同一个时间段发生(交替执行)
并行:两个或多个事件在同一时刻发生(同时执行)
进程;一个内存中运行的应用程序,每个进程都拥有一个独立的空间,一个应用程序可以同时运行多个进程;进程也是程序执行的一次过程,是系统运行程序的基本单位;系统运行一个程序就是一个线程从创建到消亡的过程。
线程:线程是进程的一个执行单元,负责当前进程中程序的执行,一个进程中至少有一个线程,拥有多个线程的 程序称为多线程程序。
即一个程序运行后至少有一个进程,一个进程可以包含多个线程.
线程的调度:
分时调度:所有线程轮流使用CPU的使用权,平均分配每个线程占用CPU的时间。
抢占式调度:优先让优先级高的线程使用CPU,如果线程的优先级相同,那么会随机选择一个,我们的Java使用的就是抢占式调度。
主线程:执行主方法的线程,执行从main方法开始,从上往下依次执行.JVM执行main方法,main方法会进入到栈内存,JVM会找操作系统开辟一条通向CPU的执行路径, CPU可以通过这个路径执行主方法,就称为main线程。
只有主线程的程序也称单线程程序,单线程的弊端就是一旦出错,程序会中断执行
//只有主线程的程序也称单线程程序,单线程的弊端就是一旦出错,程序会中断执行
public class ThreadDemo01 {
public static void main(String[] args) {
Demo demo01=new Demo("小明");
Demo demo02=new Demo("小红");
demo01.run();
System.out.println(1/0);//出现异常,不会继续执行下面的代码
demo02.run();
}
}
class Demo{
private String name;
public Demo() {
// TODO Auto-generated constructor stub
}
public Demo(String name) {
// TODO Auto-generated constructor stub
this.name=name;
}
public void run(){
for (int i = 0; i < 5; i++) {
System.out.println(name+i);
}
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
二、多线程
多线程概念:
java.lang.Thread类代表线程,所有线程对象必须是Thread类或者其子类的对象,Java允许应用程序并发的执行多个线程 每个线程都有一个优先级,优先执行优先级高的线程。
创建多线程的方法,一种是声明为Thread类的子类,该子类必须重写Thread类的run()方法,还有一种是声明实现Runnable接口的类,该类实现run方法,然后将该类作为参数,在创建Thread类传递。
1.Thread类的子类
第一种方式:
声明为Thread类的子类,该子类必须重写Thread类的run()方法
实现方法:
1.创建一个类,继承Thread类并重写Thread类中的run方法(设置线程任务)。
2.创建对象,调用Thread类中的方法start(),开启新线程
void start():使线程开始执行,Java虚拟机调用该线程的run方法。结果是两个线程并发的执行,当前线程(main线程),和另一个线程(新创建的,执行run方法)
注意:
1.多次启动一个线程是非法的,特别是线程已经结束执行后,不能重新启动。
2.Java属于抢占式调度,哪个线程优先级高,哪个线程先执行;同一个优先级,随机选择一个执行,结果随机性。
public class ThreadDemo02 {
public static void main(String[] args) {
//2.创建对象,调用Thread类中的方法start(),开启新线程
Thread01 th = new Thread01("小明");
th.start();
//设置主线程执行程序
for (int i = 0; i <5; i++) {
System.out.println("main"+"==>"+i);
}
}
}
// 1.创建一个类,继承Thread类并重写Thread类中的run方法(设置线程任务)。
class Thread01 extends Thread{
String name;
public Thread01(String name){
this.name=name;
}
@Override
public void run() {
// TODO Auto-generated method stub
for (int i = 0; i <5; i++) {
System.out.println(name+"==>"+i);
}
}
}
3.Thread类常用方法
Thread类常用方法:
public String getName():获取当前线程名称。
public void setName(String name):设置线程名称。
*还可以使用带参数的构造方法进行名称设置,调用父类的带参构造方法,把线程名称传递给父类,让父类给子线程起一个名字。
public void start():导致现次开始执行,Java虚拟机调用此线程的run方法。
public void run():此线程要执行的任务在此处定义代码。
public static void sleep(long millis):使当前正在执行的进程以指定毫秒数暂停,到时间后继续执行。
public static Thread currentThread():返回对当前正在执行的线程对象的引用。
public class ThreadDemo03 {
public static void main(String[] args) {
Thread02 th1=new Thread02();
th1.start();//输出结果:Thread-0,不进行命名后面就是Thread-1,Thread-2....
Thread02 th2=new Thread02();
th2.setName("带参数");
th2.start();//输出结果:带参数
Thread02 th3=new Thread02("父类参数");
th3.start();//输出结果:父类参数
// public static void sleep(long millis):使当前正在执行的进程以指定毫秒数暂停
try {
th2.sleep(1000);//暂停1000毫秒,即1秒后在执行
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}//单位为毫秒
}
}
class Thread02 extends Thread{
public Thread02(){}
//使用带参数的构造方法进行名称设置,调用父类的带参构造方法,把线程名称传递给父类,让父类给子线程起一个名字
public Thread02(String name){
super(name);
}
@Override
public void run() {
// TODO Auto-generated method stub
//public String getName():获取当前线程名称
System.out.println(getName());//输出结果:Thread-0,不进行命名后面就是Thread-1,Thread-2....
//public static Thread currentThread():返回对当前正在执行的线程对象的引用
Thread t=Thread.currentThread();
System.out.println(t);//输出结果:Thread[Thread-0,5,main]
}
}
3.Runnable接口
Runnable接口:由那些打算通过某一些线程执行其实例的类来实现,类必须定义一个称为run的无参构造方法。
java.lang.Thread类构造方法:
Thread(Runnable target):分配新的Thread对象
Thread(Runnable target,String name):分配新的Thread对象
实现方法:
1.定义一个Runnable接口的实现类,并重写run()方法。
2.创建实现类对象,并创建Thread类对象,并将实现类对象作为参数传递给Thread类对象。
3.调用start方法。
public class ThreadDemo04 {
public static void main(String[] args) {
// 2.创建实现类对象,并创建Thread类对象,并将实现类对象作为参数传递给Thread类对象
RunnableDemo demo = new RunnableDemo();
Thread th = new Thread(demo);
// 3.调用start方法
th.start();//输出结果:实现Runnable接口,创建多线程
}
}
//1.定义一个Runnable接口的实现类,并重写run()方法
class RunnableDemo implements Runnable{
@Override
public void run() {
// TODO Auto-generated method stub
System.out.println("实现Runnable接口,创建多线程");
}
}
4.Runnable的优点
实现Runnable接口比继承Thread类所具有的优势:
1.适合多个相同的程序代码的线程共享一个资源。
2.避免单继承的局限性。
3.增强程序的扩展性,降低了程序的耦合性。
实现Runnable接口,把设置线程任务和开启新线程进行了分类
4.线程池只能放入实现Runnable或Callable类线程,不能直接放入继承Thread的类。