程序:程序是一段静态的代码
进程:进程是程序(一段代码)的一次动态执行过程
线程:线程是更小的执行单位,是进程执行过程中其中的执行线索
主线程:即main线程,当JVM加载代码发现main方法后,会启动一个线程,该线程为主线程
多线程:如果在main方法中创建了其他线程,则JVM就会在主线程和其他线程之间轮流切换,保证每个线程都有机会使用CPU资源,即使main方法执行完最后的语句,但JVM会等待所有线程结束后才结束程序
线程状态:
新建状态: New
当Thread类或其子类的对象被声明并创建时,新生的线程对象处于新建状态
运行状态:Runnable
当线程调用start()方法后并且JVM将CPU使用权切换至该线程时
中断状态: Timed_Waiting
sleep(),wait()方法可将线程主动置于中断状态;当该线程无CPU使用权,或者执行出错时自动进入中断状态
死亡状态:Terminated
run()执行或强制结束时
1、使用Thread子类
//创建线程方式一:继承Thread类,重写run()方法,调用start开启线程
public class Threadtest extends Thread {
//run方法线程体
@Override
public void run() {
for (int i1 = 0; i1 < 2000; i1++) {
System.out.println("===="+i1);
}
}
public static void main(String[] args) {
//main主线程
//创建一个线程对象
Threadtest threadtest = new Threadtest();
//调用start()方法开启线程
threadtest.start();
for (int i = 0; i < 2000; i++) {
System.out.println("+++" + i);
}
}
}
2、使用Thread类(实现Runnable接口)
//创建线程方式二:实现runnable接口,重写run方法,执行线程需要丢入runnable接口实现类
public class Threadtest implements Runnable{
//run方法线程体
@Override
public void run() {
for (int i1 = 0; i1 < 2000; i1++) {
System.out.println("===="+i1);
}
}
public static void main(String[] args) {
//创建runnable接口实现类对象
Threadtest threadtest = new Threadtest();
//创建一个线程对象,通过对象(代理)开启线程
new Thread(threadtest).start();
//等同于 new Thread(threadtest).start()
for (int i = 0; i < 2000; i++) {
System.out.println("+++" + i);
}
}
}
1、完全解耦:在实现Runnable接口的类中不创建线程,在main方法中窜创建,这目标对象与线程不是组合关系,类中不包含对线程对象的引用。即创建目标对象的类不包含线程对象,在引用时重新创建线程对象。
2、弱耦合:目标对象可以组合线程,让线程做为自己的成员。即创建目标对象的类组合线程对象。
1、start():进入排队状态
2、run():使用CPU资源时执行该方法体
3、sleep():休眠
4、isAlive():是否死亡
5、currentThread():返回当前运行线程
6、interrupt():结束休眠
1、线程同步机制:当一个线程A使用synchronized方法时,其他线程想使用这个synchronized方法就必须等待,直到线程A使用完该synchronized方法。
2、线程同步:当若干个线程都需要使用一个synchronzed修饰的方法时,多个线程调用该方法时必须遵守同步机制。
当出现某个线程占用该synchronized方法而不能结束时,应当做出一定协调
1、使用wait()方法将不能结束的线程进入中断状态,让出CPU使用权
2、在协调后,使用notify(一个线程继续),、或者notifyAll(所有线程,先中断先继续)让未执行的方法体从中断处继续执行
在线程A执行时,联合B。则A立刻中断执行,一直等到它联合的线程B执行完毕,A再重新排队等待CPU资源,才恢复执行。
public class Threadtest implements Runnable {
@Override
public void run() {
for (int i = 0; i < 100; i++) {
System.out.println(i + "号不要脸插队");
}
}
public static void main(String[] args) {
//线程启动
Thread thread = new Thread(new Threadtest());
thread.start();
//主线程
for (int i = 0; i < 100; i++) {
if(i==50){
try {
thread.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println(i + "号同学排队");
}
}
}
1、threadx.setDaemon(true);该方法将线程设置为守护线程,守护线程再所有用户线程执行结束时立刻结束运行,无论其代码是否执行完毕。
public class Threadtest {
public static void main(String[] args) {
Thread thread1 = new Thread(new LORD());
Thread thread2 = new Thread(new P());
thread1.setDaemon(true);//默认是false,表示为用户线程,true为守护线程
thread1.start();
thread2.start();
}
}
class LORD implements Runnable{
@Override
public void run() {
while(true) {
System.out.println("LORD在看着你");
}
}
}
class P implements Runnable{
@Override
public void run() {
for (int i = 0; i < 36500; i++) {
System.out.println("你不知道");
}
System.out.println("============你去看他了==========");
}
}
当java程序包含GUI时,JVM会开辟更多线程,其中有两个线程比较重要AWT-EventQuecue和AWT-Windows,其分别处理事件和负责绘制窗口到桌面。
可以在事件中加入线程或者切换线程来达到程序目的。即在AWT-EventQuecue中启动其它线程或者使其它线程中断。
1、线程调用start()方法可以使一个线程成为可运行的,但是它不一定立即开始运行。
2、线程新建后,可以调用run方法进入排队状态。
3、run()方法是Runnable接口中的方法。
4、一个进程可以产生多线程。
5、wait()方法、notify()及notifyAll()方法在java.lang.Object中。
6、线程不调用start方法,JVM就不会把它当作一个线程来对待(JVM管理的线程队列有这个线程)。
7、线程处于“新建”状态时(在调用start方法之前),线程调用isAlive()方法返回的值是false。
8、一个线程A调用synchronized方法期间,其他线程不可以能成功调用这个synchronized方法。
9、一个线程A调用synchronized方法期间,执行sleep方法进入中断后,其他线程也不能成功调用这个synchronized方法。
10、新建状态的线程调用isAlive()方法返回的值是false。
11、currentThread()方法是Thread类中的static方法,该方法返回当前正在使用CPU资源的线程.
12、wait()、notify()和notifyAll()都是Object类中的final方法,被所有的类继承、且不允许重写的方法。
13、一个因执行wait方法进入中断状态的线程,需要其他线程执行notify()或notifyAll()通知它结束中断状态。
14、一个线程在执行同步方法时,如果执行wait()方法,使本线程进入中断,就允许其它线程使用这个同步方法。
15、javax.swing.Timer类称为计时器线程,计时器的监视器必须是组件类的子类的实例,否则计时器无法启动。
16、线程在执行完run()方法之前,如果再次让线程执行start方法,就会发生ILLegalThreadStateException 异常。