赞
踩
写在前面: 多线程大家应该也不会陌生,同时也是面试的超级重点,掌握了多线程编程有利解决许多项目的并发性问题,提高自身硬实力。
并发编程的本质是充分利用cpu资源。
硬件:CPU、磁盘、网络、内存
软件: 线程数量、JVM内存分配、网络通信机制(BIO、NIO、AIO)、磁盘IO
并行:同一时刻,多个线程同时执行。(多个CPU同时执行多个线程)
并发:同一时刻,多个线程交替执行。(一个CPU交替执行线程)
用户注册案例,异步线程调度:
@RestController public class UserController { @Autowired IUserService userService; @Autowired SmsClient smsClient; @PostMapping("/user") public String addUser(User user) { long start = System.currentTimeMillis(); userService.insert(user); long end = System.currentTimeMillis(); return "SUCCESS:" + (end - start); } //创建一个线程池对象 /** * 参数信息: * int corePoolSize 核心线程大小 * int maximumPoolSize 线程池最大容量大小 * long keepAliveTime 线程空闲时,线程存活的时间 * TimeUnit unit 时间单位 * BlockingQueue<Runnable> workQueue 任务队列。一个阻塞队列 */ @PostMapping("/sms/user") public String register(User user) { ThreadPoolExecutor pool = new ThreadPoolExecutor(4, 4, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingDeque<>(10)); long start = System.currentTimeMillis(); userService.insert(user); //异步. Future -> //会创建N个线程 //MQ来代替 pool.submit(new Runnable() { @Override public void run() { smsClient.sendSms("xxxxx"); } }); long end = System.currentTimeMillis(); pool.shutdown(); return "SUCCESS:" + (end - start); } }
Java线程的状态有6钟
public enum State {
// 创建
NEW,
// 运行时
RUNNABLE,
// 阻塞
BLOCKED,
// 等待,死死等待
WAITING,
// 超时等待
TIMED_WAITING,
// 销毁
TERMINATED;
}
需要注意的是,操作系统中的线程除去new
和terminated
状态,一个线程真实存在的状态,只有:
ready
:表示线程已经被创建,正在等待系统调度分配CPU使用权。running
:表示线程获得了CPU使用权,正在进行运算waiting
:表示线程等待(或者说挂起),让出CPU资源给其他线程使用Java创建Thread类调用start方法,底层是把线程放到一个组里面,然后调用一个本地方法start0;方法底层是C++;Java无法操作硬件。
new Thread().start(); // 启动一个线程
Thread t1 = new Thread();
t1.run(); // 调用实例方法
如下代码:
public synchronized void start() { /** * This method is not invoked for the main method thread or "system" * group threads created/set up by the VM. Any new functionality added * to this method in the future may have to also be added to the VM. * * A zero status value corresponds to state "NEW". */ if (threadStatus != 0) throw new IllegalThreadStateException(); /* Notify the group that this thread is about to be started * so that it can be added to the group's list of threads * and the group's unstarted count can be decremented. */ group.add(this); boolean started = false; try { start0(); started = true; } finally { try { if (!started) { group.threadStartFailed(this); } } catch (Throwable ignore) { /* do nothing. If start0 threw a Throwable then it will be passed up the call stack */ } } } // 调度本地方法 private native void start0();
Java调用本地方法start0
后由JVM(底层c++)去执行相应的事情发起指令到系统去做线程调度,系统调度CPU,将线程启动信息返回给jvm,然后响应回给Java中。如下图:
线程会在run方法执行结束后终止
stop()
方法终止线程。public class TestDemo extends Thread{ @Override public void run() { //线程会执行的指令 try { Thread.sleep(2000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("Come in"); } public static void main(String[] args) { TestDemo testDemo = new TestDemo(); testDemo.start(); testDemo.stop(); //不建议 强制终止这个线程。 //发送终止通知 } }
interrupt()
告知线程终止public class InterruptDemo02 implements Runnable { @Override public void run() { // 判断线程是否已经被中断 while (!Thread.currentThread().isInterrupted()) { //false try { TimeUnit.SECONDS.sleep(200); } catch (InterruptedException e) { e.printStackTrace(); //可以不做处理, //继续中断 -> Thread.currentThread().interrupt(); //再次中断 //抛出异常。。 } } System.out.println("processor End"); } public static void main(String[] args) throws InterruptedException { Thread t1 = new Thread(new InterruptDemo02()); t1.start(); Thread.sleep(1000); t1.interrupt(); // 中断线程 //Thread.interrupted() ;//复位 } }
总结:
Thread.currentThread().isInterrupted()
的状态来对线程做操作sleep()
、join()
、wait()
方法都会抛出InterruptedException
的异常c++对线程状态设置源码:
void os::interrupt(Thread*thread){ assert(Thread::current()==thread||Threads_lock->owned_by_self(), "possibility of dangling Thread pointer"); OSThread*osthread=thread->osthread(); if(!osthread->interrupted()){ osthread->set_interrupted(true); //设置一个中断状态 // More than one thread can get here with the same value of osthread, // resulting in multiple notifications. We do, however, want the store // to interrupted() to be visible to other threads before we execute unpark(). OrderAccess::fence(); ParkEvent*const slp=thread->_SleepEvent; //如果是sleep中,唤醒 if(slp!=NULL)slp->unpark(); } // For JSR166. Unpark even if interrupt status already was set if(thread->is_Java_thread()) ((JavaThread*)thread)->parker()->unpark(); ParkEvent*ev=thread->_ParkEvent; if(ev!=NULL)ev->unpark(); }
以下文章补充:interrupt的知识、interrupt方法
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。