程序、进程与线程
一:概念理解
程序:静态的代码,应用软件执行的蓝本 进程:程序的一次动态执行过程,对应了从代码加载、执行至执行完毕的一个完整过程。 线程:比进程更小的执行单位,一个进程在执行过程中可以产生多个线程。
操作系统中使用分时管理各个进程,按时间片轮流执行每个进程。Java 的多线程就是在操作系统每次分时给 Java 程序一个时间片的 CPU 时间内,在若干独立的可控制的线程之间进行切换。 Java 程序从 main 方法开始执行,当 JVM 加载代码,发现 main 方法之后会启动一个线程,这个线程是主线程,在 main 方法执行的过程中启动的线程称为该程序的其他线程。当发现程序中包含主线程和其他线程时,JVM 会在主线程和其他线程之间轮流切换,保证每个线程都有机会使用 CPU 资源。 二:代码分析
/**
* 分析程序:
* 1. JVM 首先将 CPU 资源分配给主线程,主线程在分配时执行了:
* //创建线程
* SpeakHello speakHello = new SpeakHello();
* SpeakNiHao speakNiHao = new SpeakNiHao();
* //启动线程
* speakHello.start();
* speakNiHao.start();
* 2. 开始执行 for 循环,for 循环为啥没执行完呢?
* 主线程在使用 CPU 资源的时候执行了:
* speakHello.start();
* speakNiHao.start();
* 所以 JVM 知道已经有三个线程需要轮流切换使用 CPU 资源
* 3. speakNiHao.start() 的作用是通知 JVM: 咳咳咳,老子在等着你给我分配 CPU 资源
* @author guozhenZhao
* @date 2018年12月22日
*/
public class ThreadTest {
//主程序(主线程)
public static void main(String[] args) {
//创建线程
SpeakHello speakHello = new SpeakHello();
SpeakNiHao speakNiHao = new SpeakNiHao();
//启动线程
speakHello.start();
speakNiHao.start();
for (int i = 1; i <= 20; i++) {
System.out.print("大家好"+i+" ");
}
}
}
//线程一
class SpeakHello extends Thread{
@Override
public void run() {
for (int i = 1; i <= 20; i++) {
System.out.print("hello"+i+" ");
}
}
}
//线程二
class SpeakNiHao extends Thread{
@Override
public void run() {
for (int i = 1; i <= 20; i++) {
System.out.print("您好"+i+" ");
}
}
}
synchronized关键字的理解
package com.zgz.multi.sync001;
/**
* 两种情况:
* 一:
* 关键字synchronized取得的锁都是对象锁,而不是把一段代码(方法)当作锁
* 所以代码中那个线程先执行synchronized关键字的方法,哪个线程就持有该方法所属对象的锁(lock)
* 二:
* 在静态方法上加synchronized关键字,表示锁定.class类,类一级别的锁(独占这个类)
* @author guozhenZhao
* @date 2018年12月22日
*/
public class MultiThread {
private static int num = 0;
public synchronized void printNum(String tag) {
try {
if(tag.equals("a")) {
num = 100;
System.out.println("tag a, set num over");
Thread.sleep(1000);
}else {
num = 200;
System.out.println("tag b, set num over");
}
System.out.println("tag: "+tag+", num=" + num);
} catch (Exception e) {
e.printStackTrace();
}
}
//注意观察run方法输出顺序
public static void main(String[] args) {
//两个不同的对象
final MultiThread m1 = new MultiThread();
final MultiThread m2 = new MultiThread();
//创建线程t1、t2
Thread t1 = new Thread(new Runnable() {
@Override
public void run() {
m1.printNum("a");
}
});
Thread t2 = new Thread(new Runnable() {
@Override
public void run() {
m2.printNum("b");
}
});
//通知jvm,有线程在等待执行
t1.start();
t2.start();
}
}