博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Java并发总结一 :1~2
阅读量:4290 次
发布时间:2019-05-27

本文共 5164 字,大约阅读时间需要 17 分钟。

1.并发多面性

多处理器的web服务器:为每个请求分配一个线程。

单处理器:用户界面,创建单独线程来响应用户输入
仿真:动画中,解决大量的独立动作

2.基本线程机制

底层机制:切分CPU时间,每个线程都觉得自己一直在占用CPU时间

2.1 定义任务

继承runnable接口,并覆盖run方法

public class MyTask implements Runnable{
@Override public void run() { for (int i = 0; i < 3; i++) { System.out.println(Thread.currentThread().getId()); Thread.yield(); } }}

2.2 使用Thread类创建线程

//使用构造方法传入2.1中任务Thread thread=new Thread(new MyTask());

2.3 使用Executors类的静态方法创建线程

ExecutorService service1=Executors.newCachedThreadPool();ExecutorService service2=Executors.newFixedThreadPool(45);ExecutorService service3=Executors.newSingleThreadExecutor();ExecutorService service4=Executors.newScheduledThreadPool(56);
  • newCachedThreadPool
    创建一个可缓存线程池,如果线程池长度超过处理需要,可灵活回收空闲线程,若无可回收,则新建线程。
  • newFixedThreadPool
    创建一个定长线程池,可控制线程最大并发数,超出的线程会在队列中等待。
  • newSingleThreadExecutor
    创建一个单线程化的线程池,它只会用唯一的工作线程来执行任务,保证所有任务按照指定顺序(FIFO, LIFO, 优先级)执行。
  • newScheduledThreadPool
    创建一个定长线程池,支持定时及周期性任务执行。

线程池的作用:

限制系统中执行线程的数量 ,可以自动或手动设置线程数量,达到运行的最佳效果;

少了浪费了系统资源,多了造成系统拥挤效率不高。用线程池控制线程数量,其他线程排队等候。一个任务执行完毕,再从队列的中取最前面的任务开始执行。若队列中没有等待进程,线程池的这一资源处于等待。当一个新任务需要运行时,如果线程池中有等待的工作线程,就可以开始运行了;否则进入等待队列。

2.4 从任务中产生返回值

继承Callable接口。

class MyReturnTask implements Callable
{
@Override public String call() throws Exception { return "some...strings"; }}

使用ExecutorService实例的submit()方法调用它。

ExecutorService e = Executors.newFixedThreadPool(10);Future
future = e.submit(new MyReturnTask());while (true) { if (future.isDone()) { System.out.println(future.get()); break; }}e.shutdown();

submit()方法返回一个Future,isDone()会检查Future是否完成。

你也可以直接调用Future的get方法,它具有阻塞作用,知道完成才会获取值。

2.5 线程休眠

第一种方式:使用Thread.sleep(n) —>可读性较差

Thread.sleep(1000);

第二种方式:使用TimeUnit类—>推荐

TimeUnit.SECONDS.sleep(3);//休眠3秒TimeUnit.MINUTES.sleep(5);//休眠5分钟TimeUnit.DAYS.sleep(8);//休眠8天

2.6 优先级

public class MyTask implements Runnable {
@Override public void run() { Thread.currentThread().setPriority(Thread.MAX_PRIORITY);//最高优先级 Thread.currentThread().setPriority(Thread.MIN_PRIORITY);//最低优先级 Thread.currentThread().setPriority(Thread.NORM_PRIORITY);//中等优先级 Thread.currentThread().setPriority(8);//优先级为8 Thread.currentThread().getPriority();// 获取 当前优先级 }}

2.7 让步

建议具有相同优先级的其他程序可以运行。

Thread.yield();

2.8 后台线程

使用Thread.setDeamon

如下,主线程退出后,后台线程也会退出,如果去掉thread.setDaemon(true)这句时,该线程将会一直循环打印下去…

public class RunTest {
public static void main(String[] args) throws InterruptedException { Thread thread = new Thread(new MyDeamonTask()); thread.setDaemon(true);//尝试下去掉这句 thread.start(); TimeUnit.MILLISECONDS.sleep(15); //主线程退出 }}class MyDeamonTask implements Runnable {
@Override public void run() { while (true) { System.out.println(Thread.currentThread()); } }}

使用ThreadFactory

class MyFactory implements ThreadFactory {
@Override public Thread newThread(Runnable r) { Thread t = new Thread(r); t.setDaemon(true);//此处也可以对进程进行其他设置,比如优先级 return t; }}public class RunTest {
public static void main(String[] args) throws InterruptedException { ExecutorService service = Executors.newCachedThreadPool(new MyFactory()); service.execute(new Runnable() { @Override public void run() { while (true){ System.out.println(Thread.currentThread().getId()+"deamon"); } } }); TimeUnit.MILLISECONDS.sleep(123); //主线程退出 }}

后台线程派生出来的线程也是后台线程

2.9直接使用Thread创建线程和任务

继承Thread类并覆盖run方法即可

class MyThread extends Thread{
@Override public void run() { //do }}

2.10 加入一个线程

public class RunTest {
public static void main(String[] args) throws InterruptedException { Thread t = new MyThread(); t.start(); t.join();//main线程被挂起,直到t线程结束 System.out.println("main..." ); }}class MyThread extends Thread {
@Override public void run() { for (int i = 0; i < 10; i++) { System.out.println(i); try { TimeUnit.MILLISECONDS.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } } }}

上述代码执行 结果如下:

如果去掉t.join(),会发现main线程将不会最后执行!

2.11 线程的异常

代码如下:主线程将不会捕获到MyThread中出现的异常

public class RunTest {
public static void main(String[] args) throws InterruptedException { Thread t = new MyThread(); try{ t.start(); }catch (Exception e){ System.out.println("catch it"); } }}class MyThread extends Thread {
@Override public void run() { throw new RuntimeException("exception~~~"); }}

使用setUncaughtExceptionHandler,修改为:

public class RunTest {    public static void main(String[] args) throws InterruptedException {        Thread t = new MyThread();        t.setUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() {            @Override            public void uncaughtException(Thread t, Throwable e) {                System.out.println("catch it...");            }        });        t.start();    }}

你可能感兴趣的文章
kafka知识点整理总结
查看>>
springboot使用JPA创建权限功能,所需要的表
查看>>
介绍Redis的各种用途以及使用场景
查看>>
Oracle分页查询,面试你值得关注!
查看>>
如何把内网IP映射到公网IP
查看>>
【工具篇】Excel文件导出从未如此简单——EasyPOI的使用
查看>>
如何将 oracle 和 mysql数据库的相互迁移
查看>>
Java并发编程:Synchronized及其实现原理
查看>>
Spring事务配置的五种方式及事务传播相关(不看后悔,一看必懂!)
查看>>
利用Mysql5.7的新特性实现多机房高可用架构
查看>>
Redis服务支持5000万的QPS,有什么好的思路?
查看>>
阿里云Redis读写分离典型场景:如何轻松搭建电商秒杀系统
查看>>
负载均衡在分布式架构中是怎么玩起来的?(
查看>>
java分布式任务调度xxl-job
查看>>
Java开发大型互联网-架构师必须掌握的分布式技术
查看>>
Java互联网架构-高并发分布式消息中间件技术ActiveMQ事务
查看>>
架构设计之高可用
查看>>
「数据库-SQL」SQL语句 in 超过1000个元素解决方案
查看>>
SQL 函数 详解
查看>>
一般人的不知道的Java 的四种引用类型
查看>>