操作系统创建一个进程并为进程分配资源,而后为进程创建一个内核级线程并为其分配处理器来运行jvm。jvm加载应用程序到内存并找到main方法,创建一个用户级线程或主线程来运行应用程序,应用程序可以调用jvm的服务来继续创建多个用户级线程。事务的原子性是指代码块的执行要么全做,要么全不做。操作系统的原子性是指代码块的执行不可分隔或中断,必须一次性全部执行完成
线程在未进入死亡状态时,不要再为其分配实体或new操作,否则会导致第一个实体无所指,但是垃圾收集器不会收集,因为jvm认为那个实体正在执行,收集后会出现问题,导致内存泄露。若两个线程初始化使用相同的目标对象,它们会共享目标对象内的成员属性,但局部变量是线程独有的,不被共享。
public class Thread implements Runnable {
// 自定义枚举类型描述java中线程状态,编号从0开始
public enum State {
// 创建状态, 线程开始之前的状态
MEW,
// 就绪状态和执行状态, 线程开始之后的状态
RUNNABLE,
// 阻塞状态, 线程等待对象锁, 类似互斥
BLOCKED,
// 等待状态, 线程执行了wait或join方法, 类似同步
WAITING,
// 等待状态且仅等待指定的时间, 线程执行了sleep(long)、wait(long)或join(long)
TIMED_WAITING,
// 终止状态, 线程的run方法执行结束,
TERMINATED;
}
// 返回当前线程的状态
public State getState() {}
// 返回当前正在执行的线程
public static native Thread currentThread();
// 线程执行start方法之后,run方法结束之前,该方法返回true
public final native boolean isAlive();
// 设置线程的优先级
public final void setPriority(int newPriority) {}
// 返回线程的优先级
public final int getPriority() {}
// 设置线程的名字
public final void setName(String name) {}
// 返回线程的名字
public final String getName() {}
// 设置线程为守护线程,必须在线程start之前调用
public final void setDaemon(boolean on) {}
// 判断线程是否为守护线程
public final boolean isDaemon() {}
// 暂时让出处理器并释放对象锁,让同优先级或更高优先级的就绪线程参与处理器调度,用于同级线程之间适当轮转
public static native void yield();
// 暂时让出处理器并睡眠指定时间且不会释放对象锁,此时所有的就绪线程都可参与处理器调度
// 该线程睡眠结束后会立即获取处理器并进入执行状态而不是就绪状态
public static native void sleep(long millis) throws InterruptedException;
// 参数nanos为纳秒,睡眠millis + nanos时间,更精确,内部通过sleep(long)实现
public static void sleep(long millis, int nanos) throws InterruptedException {}
// 当前正在执行的线程A,其内部调用线程B.join,会使当前并发执行的线程A,B串行执行
// 线程A暂时让出处理器并释放对象锁,等待线程B执行完或在指定的时间到后再执行
public final synchronized void join(long millis) throws InterruptedException {}
// 内部通过join(long)实现
public final synchronized void join(long millis, int nanos) throws InterruptedException {}
// 内部通过join(0)实现
public final void join() throws InterruptedException {}
// 让出处理器阻塞并释放对象锁,等待指定的时间后结束阻塞
public final native void wait(long millis) throws InterruptedException {}
// 内部通过wait(long)实现
public final native void wait(long millis, int nanos) throws InterruptedException {}
// 内部通过wait(0)实现,无限等待
public final native void wait() throws InterruptedException {}
// wait、notify、notifyAll都是基类Object的方法,只能在synchronized修饰的方法中调用
// 对象调用wait方法指线程等待该对象,必须由该对象调用notify或notifyAll来释放等待该对象而阻塞的线程
// notify根据优先数随机释放一个,notifyAll释放全部等待该对象而阻塞的线程
public final native void notify();
public final native void notifyAll();
// 线程A当前因wait、sleep或join进入阻塞状态,线程B当前占用处理器执行
// B中调用A.interrupt,B不会被中断,A抛中断异常跳到catch块中同时结束A的阻塞状态
// A不是阻塞状态,A.interrupt仅修改A的中断标志位不抛中断异常, 此时若A执行wait等方法会抛异常结束阻塞
// 中断异常实际由wait、sleep或join方法抛出,其内用死循环来阻塞A的执行且不断检查中断标志位
// A.interrupt修改标志位为中断,死循环抛出中断异常并立即结束
public void interrupt() {}
// 判断当前线程的中断标志位是否为中断状态,是则返回true同时清除中断状态,不是则返回false
public static boolean interrupted() {}
// 判断当前线程的中断标志位是否为中断状态,是则返回true但是不清除中断状态,不是则返回false
public boolean isInterrupted() {}
}
// 线程A、B互斥使用共享数据i,利用管程思想将A,B对i的修改操作都放到一个方法中,使对i的互斥访问转为对代码块的互斥访问
// 关键字synchronized要求线程必须获取对象锁之后才能执行其修饰的方法,类似信号量
public synchronized void doByAOrB() {
// 线程A执行到某一点后,需等待线程B的执行结果
if(Thread.currentThread().getName().equals(A)) {
// 线程A的临界区
// 线程A执行到某一点后,等待线程B的执行
this.wait();
// 或
B.join();
} else if(Thread.currentThread().getName().equals(B)) {
// 线程B的临界区
// 线程B执行完后,必须唤醒被阻塞的线程A
this.notifyAll();
}
}
// 关键字synchronized的升级,Lock锁
// synchronized是关键字,定义在语法层面,由jvm自动完成加锁解锁
// 被加锁的代码块若出现异常,jvm会自动释放锁从而避免无法释放锁而进入死锁
// Lock是接口,要通过代码实现加锁解锁,为防加锁的代码块出现异常而不能释放锁,须在finally快中释放锁
public interface Lock {
void lock();
}
// 使用线程池实现有返回结果的线程
public class MyCallable implements Callable<Object> {
// 类似Runnable接口的run方法,run没有返回值,该方法有返回值
public Object call() throws Exception {
return null;
}
}
// 创建具有5个线程的线程池
ExecutorService pool = Executors.newFixedThreadPool(5);
// 创建一个具有返回值的任务
Callable c = new MyCallable();
// 提交任务给线程池来执行,并返回Future类型的结果
Future f = pool.submit(c);
// 从Future的对象中取出call方法执行的返回结果
f.get().toString();