1. 线程
线程必须有有一个父进程线程可以拥有自己的堆栈,自己的程序计数器和自己的局部变量,但不拥有系统资源,与父进程的其他线程共享该进程的所有资源所有线程对象都必须是Thread类或其子类的实例使用继承Thread类的方法来创建线程类时,多个线程之间无法共享线程类的实例变量
public class FirstThread extends Thread {
private int i;
@Override
public void run() {
for (;i<
100;i++) {
System.out.println(getName()+
" "+i);
}
}
}
使用Runnable接口的方式创建的多个线程可以共享线程类的实例
public class SecondThread implements Runnable {
private int i;
@Override
public void run() {
for (;i<
100;i++) {
System.out.println(Thread.currentThread().getName()+
" "+i);
}
}
}
使用Callable和Future创建线程时线程的执行体就是该Callable对象的call()方法
FutureTask<Integer> task =
new FutureTask<Integer>
((Callable<Integer>)()->{
int i = 0;
for (;i<100;i++) {
System.out.println(Thread.currentThread().getName()+"的i的值:"+i);
}
return i;
});
for (int i = 0; i < 100; i++) {
System.out.println(Thread.currentThread().getName()+" 的i的值:"+i);
if (i == 20) {
new Thread(task,"有返回值的线程").start();
}
}
System.out.println("子线程的返回值:"+task.get());
2. 线程的生命周期
新建
使用new创建后处于新建状态就绪
使用start()方法后处于就绪状态(只能对新建状态的线程调用,否则会抛出异常)阻塞
线程调用sleep()方法主动放弃所占用的处理器资源,进入阻塞状态调用了阻塞式IO方法,方法返回前线程阻塞线程试图获得一个同步监视器,但该同步监视器被其他线程所持有线程在等待某个通知(notify)程序使用了suspend方法将该线程挂起死亡
run()或call()方法执行完成,线程正常结束线程抛出一个未捕获的Exception或Error使用了该线程的stop()方法结束该线程
3. 控制线程
join线程
当某个程序执行流中调用其他线程的join()方法时,调用线程将被阻塞,直到join()方法加入的join线程执行完为止后台线程(Daemon Thread)
任务是为其他线程提供服务,在后台运行将线程设置为后台进程时setDaemon(true)必须在start()方法之前调用线程睡眠
当前线程调用sleep()方法进入阻塞状态后,在其睡眠时间内不会获得执行的机会线程让步
调用yield()方法,不好阻塞该线程,只是让该线程处于就绪状态只是让该线程暂停一下,让系统的线程调度器重新调度一次(系统调度该线程时会再次执行) 当调用了yield()方法暂停之后,只有优先级与当前线程相同,或者优先级比当前线程更高的处于就绪状态的线程才会获得执行的机会改变线程优先级
调用setPriority()方法实现优先级最大为10,最小为1
4. 线程同步
任何时刻只能有一个线程可以获得对同步监视器的锁定,当同步代码块执行完成后该线程会释放对该同步监视器的锁定强制要求加锁和释放锁要出现在一个块结构中,当取得了多个锁时,必须以相反的顺序释放,且必须在与所有锁被获取时相同的范围内释放锁一个线程可以对被加锁的ReentrantLock锁再次加锁,被锁保护的代码可以调用另一个被相同锁保护的方法
5. 线程通信
wait()导致当前线程等待,知道其他线程调用该同步监视器的notify()或notifyAll()方法来唤醒该线程notify()唤醒在此同步监视器上等待的单个线程,选择是任意性的notifyAll()唤醒在此同步监视器上等待的所有线程使用Condition可以让那些已经得到Lock对象却无法继续执行的线程释放Lock对象Condition对象也可以唤醒其他处于等待的线程Condition对象被绑定在一个Lock实例上BlockingQueue中当生产者向其中放入元素时,如果该队列已满,在该线程被阻塞,当消费者取出元素时,如果该队列已空,则该线程被阻塞
6. 线程组
对线程组的控制相当于同时控制这批线程用户所创建的所有线程都属于指定线程组,如果没有显示的指定,则该线程属于默认线程组通常,子线程和创建它的父线程处于同一个线程组内线程允许中途不能改变它所属的线程组后台线程组中,当后台线程组的最后一个线程执行结束或最后一个线程被销毁后,后台线程将自动销毁ThreadLocal为每一个使用该变量的线程都会提供一个变量值的副本,使每一个线程都可以独立的改变自己的副本,而不会和其他线程的副本冲突
7. 线程池
调用线程池的shutdown()方法将会启动线程池的关闭序列,不在接受新任务,但会将所有已提交的任务执行完成,当所有线程完成后池中的所有线程都会死亡调用shutdownNow()关闭线程池时,会停止所有正在执行的活动任务,暂停处理正在等待的任务,并返回等待执行的任务列表
public static void test() {
ExecutorService pool = Executors.newFixedThreadPool(
6);
Runnable target = ()-> {
for (
int i =
0; i <
100; i++) {
System.
out.println(Thread.currentThread().getName()+
"的i的值为:"+i);
}
};
pool.submit(target);
pool.submit(target);
pool.shutdown();
}
转载请注明原文地址: https://ju.6miu.com/read-1299446.html