1.线程的三种写法:
方案一:外部类 写一个类继承自Thread,重写run方法,在这个方法加入耗时的操作或阻塞操作
方案二:内部类写法:只有这个Test1_thread这个类才会用到InnerThread
方案三:匿名内部类
public class Test1_thread {
public static void main(String[] args) {
System.out.println("主方法的开头");
MyThread myThread=new MyThread();
myThread.start();
InnerThread innerThread=new InnerThread();
innerThread.start(); //启动线程要用start(); -->jvm会自动调用 线程中run()
//匿名内部类:
Thread nimingThread=new Thread(new Runnable() {
@Override
public void run() {
for ( int i = 0; i <=100 ; i++ ) {
System.out.println("匿名内部类中i的值为:"+i);
try {
Thread.sleep(1000);
}catch ( InterruptedException e){
e.printStackTrace();
}
}
}
});
nimingThread.start();
}
//内部类写法:只有这个Test1_thread这个类才会用到InnerThread
static class InnerThread extends Thread{
@Override
public void run() {
for ( int i = 0; i <=100 ; i++ ) {
System.out.println("内部类中i的值为:"+i);
try {
Thread.sleep(1000);
}catch ( InterruptedException e){
e.printStackTrace();
}
}
}
}
}
//方案一:外部类 写一个类继承自Thread,重写run方法,在这个方法加入耗时的操作或阻塞操作
class MyThread extends Thread{
@Override
public void run() {
for ( int i = 0; i <=100 ; i++ ) {
System.out.println("i的值为:"+i);
try {
Thread.sleep(1000);
}catch ( InterruptedException e){
e.printStackTrace();
}
}
}
}
//缺点:Java 是继承,以上方法影响类的扩展性
2.线程实现的四种方式:
方案一:继承Thread类
方案二:实现runnable接口 任务对象
方案三:匿名内部类写法
方案四:函数式编程 ->lambda写法
import java.text.SimpleDateFormat;
import java.util.Date;
public class Test2_Thread_runnable {
public static void main(String[] args) {
//方法一:继承Thread类
ShowTimeThread stt=new ShowTimeThread();
stt.setName("线程1");
stt.setPriority(1);//可以设置优先级(理论上) 1-10
stt.start();
//实现二:实现runnable接口 任务对象
ShowTimeThread2 showTimeThread2=new ShowTimeThread2();
Thread t=new Thread(showTimeThread2,"线程二");
t.setPriority(10);
t.start(); //t 启动。jvm就会自动回调它配置 task中的run()
//实现三:换成匿名内部类写法
Thread thread=new Thread(new Runnable() {
@Override
public void run() {
SimpleDateFormat simpleDateFormat=new SimpleDateFormat("yyyy年MM月dd日 hh:mm:ss");
Date d=null;
while ( true ){
d=new Date();
System.out.println(Thread.currentThread().getName()+"当前的时间为:"+simpleDateFormat.format(d));
try{
Thread.sleep(1000);
}catch ( InterruptedException e){
e.printStackTrace();
}
}
}
},"Thread3");
thread.start();
//写法4:函数式编程 ->lambda写法
Thread t3=new Thread(()->{
SimpleDateFormat simpleDateFormat=new SimpleDateFormat("yyyy年MM月dd日 hh:mm:ss");
Date d=null;
while ( true ){
d=new Date();
System.out.println(Thread.currentThread().getName()+"当前的时间为:"+simpleDateFormat.format(d));
try{
Thread.sleep(1000);
}catch ( InterruptedException e){
e.printStackTrace();
}
}
},"线程四");
t3.start();
}
}
//显示时间 线程类
class ShowTimeThread extends Thread{
@Override
public void run() {
//耗时操作
SimpleDateFormat simpleDateFormat=new SimpleDateFormat("yyyy年MM月dd日 hh:mm:ss");
Date d=null;
while ( true ){
d=new Date();
System.out.println(Thread.currentThread().getName()+"当前的时间为:"+simpleDateFormat.format(d));
try{
Thread.sleep(1000);
}catch ( InterruptedException e){
e.printStackTrace();
}
}
}
}
//方案二:写一个类(任务类)实现Runnable接口,重写run()
class ShowTimeThread2 implements Runnable{
@Override
public void run() {
SimpleDateFormat simpleDateFormat=new SimpleDateFormat("yyyy年MM月dd日 hh:mm:ss");
Date d=null;
while ( true ){
d=new Date();
System.out.println(Thread.currentThread().getName()+"当前的时间为:"+simpleDateFormat.format(d));
try{
Thread.sleep(1000);
}catch ( InterruptedException e){
e.printStackTrace();
}
}
}
}
3.FutureTask
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;
public class Test3_callable {
public static void main(String[] args) {
//FutureTask对象
//方式一:内部类
// FutureTask task=new FutureTask<>(new Callable< Integer >() {
// @Override
// public Integer call() throws Exception {
// for ( int i = 0; i <= 100; i++ ) {
// Thread.sleep(1000);
// count +=i;
// }
// return null;
// }
// });
//方式二:lambda表达式
FutureTask task=new FutureTask<>(()->{
int count=0;
for ( int i = 0; i <= 100; i++ ) {
Thread.sleep(100);
count +=i;
}
return count;
});
//创建线程,与一个FutureTask任务绑定
Thread thread=new Thread(task); //Thread(Runnable)
//启动线程
thread.start();
try {
System.out.println("1 + 2 + 3 + ... +100="+task.get()); //等到两种情况跳出:1.任务执行出错 2.任务执行完成
//System.out.println("1 + 2 + 3 + ... +100="+task.get(1, TimeUnit.SECONDS));
}catch ( InterruptedException e1 ){
e1.printStackTrace();
}catch ( ExecutionException e ){
e.printStackTrace();
}
System.out.println("主线程中其它的代码..."); //因为调用了get(),这是阻塞式的方法。它要等到出结果之后,主线程才会继续
}
}
4.线程池
import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicInteger;
public class Test4_pool {
public static void main(String[] args) {
int corePoolSize=2;
int maxPoolSize=4;
long keepAliveTime=10;
TimeUnit unit=TimeUnit.SECONDS; //enum枚举 常量
BlockingQueue workQueue=new ArrayBlockingQueue<>(2);
ThreadFactory threadFactory=new NameThreadFactory();
RejectedExecutionHandler handler=new MyIgnorePolicy();
ThreadPoolExecutor executor=null;
try {
executor=new ThreadPoolExecutor(corePoolSize,maxPoolSize,keepAliveTime,unit,workQueue,threadFactory,handler);
executor.prestartAllCoreThreads();
int count=10;
for ( int i = 0; i < count; i++ ) {
RunnableTask task=new RunnableTask(String.valueOf(i));
executor.submit(task); //提交任务到线程池 还有4个任务无法执行
}
}finally {
assert executor!=null; //断言,可开关 -ea -da
executor.shutdown();
}
}
static class NameThreadFactory implements ThreadFactory{
private final AtomicInteger threadId=new AtomicInteger(1);
@Override
public Thread newThread(Runnable r) {
Thread t=new Thread(r,"线程一"+threadId.getAndIncrement()); // i++ => i I+1 => 赋值
System.out.println(t.getName()+" 已经被创建");
return t;
}
}
public static class MyIgnorePolicy implements RejectedExecutionHandler{
@Override //被拒绝的任务 线程池对象
public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
doLog(r,executor);
}
private void doLog(Runnable runnable,ThreadPoolExecutor e){
//可做日志记录等
System.out.println("线程池:"+e.toString()+runnable.toString()+" 被拒绝执行");
}
}
static class RunnableTask implements Runnable{
private String name;
public RunnableTask(String name){
this.name=name;
}
@Override
public void run() {
try{
System.out.println(this.toString()+ " is running!");
//让任务执行慢点
Thread.sleep(3000);
}catch ( InterruptedException e ){
e.printStackTrace();
}
}
@Override
public String toString() {
return "RunnableTask [name="+name+"]";
}
}
}
线程池原理图:
线程生命周期:
相关的源代码:
// Public constructors and methods
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue workQueue) {
this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
Executors.defaultThreadFactory(), defaultHandler);
}
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue workQueue,
ThreadFactory threadFactory) {
this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
threadFactory, defaultHandler);
}
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue workQueue,
RejectedExecutionHandler handler) {
this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
Executors.defaultThreadFactory(), handler);
}
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue workQueue,
ThreadFactory threadFactory,
RejectedExecutionHandler handler) {
if (corePoolSize < 0 ||
maximumPoolSize <= 0 ||
maximumPoolSize < corePoolSize ||
keepAliveTime < 0)
throw new IllegalArgumentException();
if (workQueue == null || threadFactory == null || handler == null)
throw new NullPointerException();
this.acc = System.getSecurityManager() == null ?
null :
AccessController.getContext();
this.corePoolSize = corePoolSize;
this.maximumPoolSize = maximumPoolSize;
this.workQueue = workQueue;
this.keepAliveTime = unit.toNanos(keepAliveTime);
this.threadFactory = threadFactory;
this.handler = handler;
}
public void execute(Runnable command) {
if (command == null)
throw new NullPointerException();
int c = ctl.get();
if (workerCountOf(c) < corePoolSize) {
if (addWorker(command, true))
return;
c = ctl.get();
}
if (isRunning(c) && workQueue.offer(command)) {
int recheck = ctl.get();
if (! isRunning(recheck) && remove(command))
reject(command);
else if (workerCountOf(recheck) == 0)
addWorker(null, false);
}
else if (!addWorker(command, false))
reject(command);
}
5.中断:
interrupt()方法:其作用是中断此线程(此线程不一定是当前线程,而是指调用该方法的Thread实例所代表的线程),但实际上只是给线程设置一个中断标志,线程仍会继续运行。
interrupted()方法:作用是测试当前线程是否被中断(检查中断标志),返回一个boolean并清除中断状态,第二次再调用时中断状态已经被清除,将返回一个false。
public class Test5_Interrupt {
public static void main(String[] args) {
//通过interrupt()方法检测线程是否被中断
//Thread.currentThread() 主线程
System.out.println(Thread.currentThread().getName()+"线程是否中断:"+Thread.interrupted());
//设置线程中断
Thread.currentThread().interrupt();
//Thread.currentThread().stop();
//通过interrupt()方法检测线程是否被中断
System.out.println(Thread.currentThread().getName()+"线程是否被中断:"+Thread.interrupted()); //返回true后,恢复状态
//检测interrupt()是否会清除线程状态
System.out.println(Thread.currentThread().getName()+"线程是否被中断:"+Thread.interrupted());
}
}
interrupt()和interrupted()的源代码:
public void interrupt() {
if (this != Thread.currentThread())
checkAccess();
synchronized (blockerLock) {
Interruptible b = blocker;
if (b != null) {
interrupt0(); // Just to set the interrupt flag
b.interrupt(this);
return;
}
}
interrupt0();
}
public final void checkAccess() {
SecurityManager security = System.getSecurityManager();
if (security != null) {
security.checkAccess(this);
}
}
public static boolean interrupted() {
return currentThread().isInterrupted(true);
}
6.isInterrupted()
isInterrupted()方法:作用是只测试此线程是否被中断 ,不清除中断状态。
public class Test6_isInterrupted {
public static void main(String[] args) {
//当前线程
Thread thread=Thread.currentThread();
//检测当前线程是否被中断
System.out.println(thread.getName()+"线程是否被中断:"+thread.isInterrupted()); //false
thread.interrupt();
//检测当前线程是否被中断
System.out.println(thread.getName()+"线程是否被中断:"+thread.isInterrupted()); //true
//检测线程中断状态是否会被清除
System.out.println(thread.getName()+"线程是否被中断:"+Thread.interrupted());//true
try {
//线程休眠2s
Thread.sleep(20000); //本来要在main线程中20 s的,但因为interrupt()被调用了。所以sleep被打断
System.out.println(thread.getName()+"线程休眠未被中断...");
}catch ( Exception e ){
e.printStackTrace();
System.out.println(thread.getName()+"线程休眠被中断...");
//检测当前线程是否被中断
System.out.println(thread.getName()+"线程是否被中断:"+thread.isInterrupted()); //false
}
System.out.println(thread.getName()+"线程是否被中断:"+thread.isInterrupted());
}
}
isInterrupted()源代码:
public boolean isInterrupted() {
return isInterrupted(false);
}
private native boolean isInterrupted(boolean ClearInterrupted);
7.中断线程并抛出异常后重新抛出异常
public class Test7_ReThrowInterruptException {
public static void main(String[] args) throws InterruptedException {
//当前线程
Thread thread=Thread.currentThread();
try {
//检测当前线程是否被中断
thread.interrupt();
//线程休眠3s
Thread.sleep(3000);
}catch ( InterruptedException e ){
System.out.println(thread.getName()+"抛出InterruptedException中断异常");
System.out.println(thread.getName()+"做一些清理工作");
throw e;
}
}
}
8.ReInterrupted
import java.text.SimpleDateFormat;
import java.util.Date;
public class Test8_ReInterrupted extends Thread{
public static void main(String[] args) throws InterruptedException {
//当前线程
String threadName=Thread.currentThread().getName();
Test8_ReInterrupted reInterrupted=new Test8_ReInterrupted();
System.out.println(printDate()+threadName+"线程启动");
//启动新线程
reInterrupted.start();
//主线程休眠3秒
Thread.sleep(3000);
System.out.println(printDate()+threadName+"设置子线程中断");
//对新线程设置线程中断
reInterrupted.interrupt();
//主线程休眠3秒
Thread.sleep(3000);
System.out.println(printDate()+threadName+"运行结束");
}
@Override
public void run() {
//当前线程
String threadName=Thread.currentThread().getName();
int i=0;
//for 循环等待线程中断 只要当前线程不是中断态,则继续,是中断,则退出当前线程
while ( !Thread.currentThread().isInterrupted() ){
System.out.println(printDate()+threadName+"线程正在执行第"+(++i)+"次");
try {
//执行3次
//线程阻塞,如果线程收到中断操作信号将抛出异常
Thread.sleep(1000);
}catch ( InterruptedException e ){
System.out.println(printDate()+threadName+"线程正在执行");
//检测线程是否被中断
System.out.println(printDate()+threadName+"的状态:"+this.isInterrupted());//false
//如果需要维护中断状态,则需要重新设置中断状态
//如果不需要。则不用调用。 如果调用interrupt()的话,则当前线程的状态变为中断,这个while循环退出,程序结束
Thread.currentThread().interrupt();//true
}
System.out.println(printDate()+threadName+"线程是否被中断:"+this.isInterrupted());
System.out.println(printDate()+threadName+"线程退出");
}
}
private static String printDate(){
SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
return sdf.format(new Date())+" ";
}
}



