精华内容
下载资源
问答
  • 主要介绍了Java多线程及线程安全实现方法解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
  • 多线程及线程安全问题解决方案 1. 多线程 1.1 多线程的优缺点 优点:1. 提升资源利用率 2. 提高用户体验 缺点: 1. 降低了其他线程的执行概率 2. 用户会感受到软件的卡顿问题 3. 增加的系统,资源压力 4. ...

    多线程及线程安全问题解决方案

    1. 多线程

    1.1 多线程的优缺点
    优点:1. 提升资源利用率
    	 2. 提高用户体验
    	 
    缺点:
    	1. 降低了其他线程的执行概率
    	2. 用户会感受到软件的卡顿问题
    	3. 增加的系统,资源压力
    	4. 多线程情况下的共享资源问题,线程冲突,线程安全问题
    
    1.2 创建自定义线程类的两种方式
    class Thread类
    	Java中的一个线程类
    	Thread类是Runnable接口的实现类,同时提供了很多线程的操作使用的方法。
    	
    interface Runnable接口
    	这里规定了what will be run?
    	里面只有一个方法 run方法
    
    方式一:
    	自定义线程类,继承Thread类,重写run方法
    	创建自定义线程对象,直接调用start方法,开启线程
    	
    方式二:
    	自定义线程类,遵从Runnable接口
    	使用自定义遵从接口Runnable实现类对象,作为Thread构造方法参数
    	借助于Thread类对象和start方法,开启线程
    
    【推荐】
    	以上两种方式,推荐使用方式二,遵从Runnable接口来完成自定义线程,不影响正常的继承逻辑,并且可以使用匿名内部类来完成线程代码块的书写
    
    1.3 Thread类需要了解的方法
    构造方法 Constructor
    	Thread();
    		分配一个新的线程对象,无目标,无指定名字
    	Thread(Runnable target);
    		创建一个新的线程对象,并且在创建线程对象的过程中,使用Runnable接口的实现类
    		对象作为执行的线程代码块目标
    	Thread(String name);
    		创建一个新的线程,无指定目标,但是指定当前线程的名字是什么
    	Thread(Runnable target, String name);
    		创建一个线程的线程对象,使用Runnable接口实现类对象,作为执行目标,并且指定
    		name作为线程名
    	
    成员方法:
    	void setName(String name);
    	String getName();
    		以上两个是name属性setter和getter方法
    	void setPriority(int Priority);
    		设置线程的优先级,非一定执行要求,只是增加执行的概率
    		优先级数值范围 [1 - 10] 10最高 1最低 5默认
    	int getPriority();
    		获取线程优先级
    	void start();
    		启动线程对象
    	
    	public static void sleep(int ms);
    		当前方法是静态方法,通过Thread类调用,要求是当前所在线程代码块对应的线程,
    		进行休眠操作,休眠指定的毫秒数
    	public static Thread currentThread();
    		当前方法是静态方法,通过Thread类调用,获取当前所处代码块对应的线程对象。
    

    2. 线程安全问题和解决方案

    2.1 同步代码块
    synchronized (/* 锁对象 */) {
        
    }
    
    /*
    特征:
     	1. synchronized 小括号里面的对象是锁对象,并且要求如果是多线程的情况下,锁对象必须是同一个对象。
     	2. synchronized 大括号中的代码块就是需要进行同步的代码,或者说是加锁的代码,大括号里面的内容,有且只允许一个线程进入。
     	3. 同步代码块越短越好,在保证安全的情况下,提高性能
     
    问题:
    	1. 目前锁对象感觉很随意,存在一定的隐患
    	2. 代码层级关系很复杂,看着有点麻烦
    */
    
    2.2 同步方法
    synchronized 作为关键字来修饰方法,修饰的方法就是对应的同步方
    有且只允许一个线程进入,到底是谁来完成的加锁操作?
    
    1. 静态成员方法
    	锁对象,是当前类对应的字节码文件.class 类名.class
    2. 非静态成员方法
    	锁对象就是当前类对象 this
    
    选择同步方法是否使用static修饰问题
    	1. 如果非static修饰,要保证执行的线程对象有且只有一个,因为锁对象就是当前线程对
    象
    	
    	2. 如果是static修饰,锁对象具有唯一性,多个线程使用的锁是同一个锁。
    	
    
    2.3 Lock锁
    Java提供了一个对于线程安全问题,加锁操作相对于同步代码块和同步方法更加广泛的一种操作方式。
    1. 对象化操作。
    	创建Lock构造方法
    		Lock lock = new ReentrantLock();
    2. 方法化操作。
    	开锁:
    		unlock();
    	加锁:
    		lock();
    
    2.4 三种加锁方式的总结
    1. 一锁一线程,一锁多线程问题。
    	使用对应的锁操作对应的线程,考虑静态和非静态问题。
    	同步方法和Lock锁使用。
    	静态是一锁多目标,非静态是一锁一目标
    
    2. 涉及到同步问题时,要考虑好锁对象的选择问题
    	同步代码块,同步方法,Lock对象。
    
    展开全文
  • servlet多线程及线程安全(轉載) Servlet体系结构是建立在Java多线程机制之上的,它的生命周期是由Web容器负责的。当客户端第一次请求某个 Servlet时,Servlet容器将会根据web.xml配置文件实例化这个Servlet类。...
    servlet多线程及线程安全(轉載) 

    Servlet体系结构是建立在Java多线程机制之上的,它的生命周期是由Web容器负责的。当客户端第一次请求某个 Servlet时,Servlet容器将会根据web.xml配置文件实例化这个Servlet类。当有新的客户端请求该Servlet时,一般不会再实例化该Servlet类,也就是有多个线程在使用这个实例。 这样,当两个或多个线程同时访问同一个Servlet时,可能会发生多个线程同时访问同一资源的情况,数据可能会变得不一致。所以在用Servlet构建的Web应用时如果不注意线程安全的问题,会使所写的Servlet程序有难以发现的错误。

    实例变量不正确的使用是造成Servlet线程不安全的主要原因。下面针对该问题给出了三种解决方案并对方案的选取给出了一些参考性的建议。

    1、实现 SingleThreadModel 接口

    该接口指定了系统如何处理对同一个Servlet的调用。如果一个Servlet被这个接口指定,那么在这个Servlet中的service方法将不会有两个线程被同时执行,当然也就不存在线程安全的问题。这种方法只要将前面的Concurrent Test类的类头定义更改为:

    Public class Concurrent Test extends HttpServlet implements SingleThreadModel {
    …………
    }
      2、同步对共享数据的操作

    使用synchronized 关键字能保证一次只有一个线程可以访问被保护的区段,在本论文中的Servlet可以通过同步块操作来保证线程的安全。同步后的代码如下:

    …………
    Public class Concurrent Test extends HttpServlet { …………
    Username = request.getParameter ("username");
    Synchronized (this){
    Output = response.getWriter ();
    Try {
    Thread. Sleep (5000);
    } Catch (Interrupted Exception e){}
    output.println("用户名:"+Username+"
    ");
    }
    }
    }
      3、避免使用实例变量

    本实例中的线程安全问题是由实例变量造成的,只要在Servlet里面的任何方法里面都不使用实例变量,那么该Servlet就是线程安全的。

    修正上面的Servlet代码,将实例变量改为局部变量实现同样的功能,代码如下:

    ……
    Public class Concurrent Test extends HttpServlet { public void service (HttpServletRequest request, HttpServletResponse
    Response) throws ServletException,IOException {
    Print Writer output;
    String username;
    Response.setContentType ("text/html; charset=gb2312");
    ……
    }
    }
    对上面的三种方法进行测试,可以表明用它们都能设计出线程安全的Servlet程序。但是,如果一个Servlet实现了 SingleThreadModel接口,Servlet引擎将为每个新的请求创建一个单独的Servlet实例,这将引起大量的系统开销。 SingleThreadModel在Servlet2.4中已不再提倡使用;同样如果在程序中使用同步来保护要使用的共享的数据,也会使系统的性能大大下降。这是因为被同步的代码块在同一时刻只能有一个线程执行它,使得其同时处理客户请求的吞吐量降低,而且很多客户处于阻塞状态。另外为保证主存内容和线程的工作内存中的数据的一致性,要频繁地刷新缓存,这也会大大地影响系统的性能。所以在实际的开发中也应避免或最小化 Servlet 中的同步代码;在Serlet中避免使用实例变量是保证Servlet线程安全的最佳选择。从Java 内存模型也可以知道,方法中的临时变量是在栈上分配空间,而且每个线程都有自己私有的栈空间,所以它们不会影响线程的安全。
    展开全文
  • java多线程及线程安全详解

    千次阅读 2018-05-18 01:12:07
    为什么要使用多线程:单线程只能干一件事 而多线程可以同时干好多事(将任务放到线程里执行 效率高)而所谓同时干并不是真正意义上的同时 只是(这里就叫CPU)cpu在每个线程中随机切换来执行 线程中要干的活...

    为什么要使用多线程:

    单线程只能干一件事  而多线程可以同时干好多事(将任务放到线程里执行  效率高)

    而所谓同时干并不是真正意义上的同时   只是(这里就叫CPU)cpu在每个线程中随机切换来执行 线程中要干的活

    多线程编写:

    1)第一种:(线程类)

    class Stu1 extends Thread{

      //重写 run方法 

    }

    调用:Stu1 su = new Stu1();

    su.start()//内部会自动调用run方法    把run方法放到线程上调用

    2)第二种:普通任务类(由于第一种类只能是单继承 就没法实现继承其他父类并且继承线程类 所以第一种方法扩展性比较差)

    直接创建线程对象    线程内干的事  放到一个自定义对象里面实现   (用到修饰设计模式)

    底层代码

    class Thread{

    private Runnable r

    public void Thread(Runnable r){ //利用有参构造将自定义对象传进来

    this.r = r;

    }

    public void start(){

      r.run();

    }

    }

    class Stu implements Runnable{}  通过实现接口   线程类底层start调用的run方法 实际就是我们自定义类中的run方法

    Thread th = new  Thread(new Stu())  //直接创建线程对象

    th.start();

    我们用第二种方法创建多线程如下:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    public static void main(String[] args) {
    //      不同线程干同一件事
            SaleWindow sw = new SaleWindow();
            Thread t1 = new Thread(sw);
            Thread t2 = new Thread(sw);
            t1.setName("窗口A");
            t2.setName("窗口B");
            t1.start();
            t2.start();
        }

     

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    public class SaleWindow implements Runnable {
        private int ticketCount = 10;
     
        @Override
        public void run() {
            // TODO Auto-generated method stub
    //      多个窗口卖票
            for(int i = 0;i<10;i++){
                if(ticketCount>0){
                    //字符串拼接信息   变量+""  就可以拼接成字符串
                    System.out.println(Thread.currentThread().getName()+"卖出"+ticketCount+"张票");
                    ticketCount--;
                    try {
                        Thread.sleep(500);
                    catch (InterruptedException e) {
                        // TODO Auto-generated catch block
    //                  e.printStackTrace();
                    }
                }
            }
        }
         
    }

     最后结果图:

    从运行结果来看:同一张票卖给了二个人  这是在现实生活中不允许的 这样就会产生线程安全问题。

    而产生线程安全问题的有三个要素必须同时满足才会产生线程安全:

    1、必须有共享资源
    2、必须是多线程环境
    3、每个线程都适用了共享资源

    而上面的例子:票是共享资源、又是多线程环境、线程执行任务的时候又使用了共享资源 所以会产生线程安全

    怎么解决线程安全?

    解决线程安全其核心:就是将某一个线程中的任务给锁(同步锁)起来,这个时候JVM就不得不等到本任务里的代码执行完以后在去执行另外一个线程里的任务。

    二种方法:

    1、同步代码块:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    public class SaleWindow implements Runnable {
        private int ticketCount = 10;
     
        @Override
        public void run() {
            // TODO Auto-generated method stub
            // 多个窗口卖票
            for (int i = 0; i < 10; i++) {//可以随意设置锁
                synchronized (this) {
                    if (ticketCount > 0) {
                        // 字符串拼接信息 变量+"" 就可以拼接成字符串
                        System.out.println(Thread.currentThread().getName() + "卖出"
                                + ticketCount + "张票");
                        ticketCount--;
                        try {
                            Thread.sleep(500);//每隔500毫秒 线程休眠 随后自己自动会唤醒(目的是为了调节线程速度)
                        catch (InterruptedException e) {
                            // TODO Auto-generated catch block
                            // e.printStackTrace();
                        }
                    }
                }
            }
        }
     
    }

     2、同步方法:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    public class SaleWindow implements Runnable {
        private int ticketCount = 10;
         //默认固定的锁对象this<br>        //将产生线程安全的代码封装到方法里并设置成同步方法
        public synchronized void syncB() {
            if (ticketCount > 0) {
                // 字符串拼接信息 变量+"" 就可以拼接成字符串
                System.out.println(Thread.currentThread().getName() + "卖出"
                        + ticketCount + "张票");
                ticketCount--;
                try {
                    Thread.sleep(500);
                catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    // e.printStackTrace();
                }
            }
        }
     
        @Override
        public void run() {
            // TODO Auto-generated method stub
            // 多个窗口卖票
            for (int i = 0; i < 10; i++) {
                syncB();
            }
        }
     
    }

     结果图:

    最后结果每个窗口不能卖同样的票解决了线程安全问题

    线程之间的通信

    (ps:线程之间的通信和线程安全无关联二者不是一回事)

    怎样才能让二个线程之间进行通信?

    线程之间是相互独立的互不联系 而真正意义上的通信是通过中间件(同步锁 必须是同一把锁)来达到线程之间通信的目的

    案例:二个线程来回交替输出一条数据(意思就是必须按照我说一句你说一句的这个规则走)

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    class BingB extends Thread {
        public void run(){
            for(int i = 0;i<5;i++){
                System.out.println("冰冰美,如花丑");
            }
        }
    }
     
    class RuH extends Thread{
        public void run(){
            for(int i = 0;i<5;i++){
                System.out.println("如花美,冰冰丑");
            }
        }
    }
     
    public class Test {
        public static void main(String[] args) {
            BingB bb = new BingB();
            RuH rh = new RuH();
            bb.start();
            rh.start();
        }
    }

     结果图:此结果不是交替出现的

    要想达到交替的目的代码如下:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    class MyLock{
        static Object o = new Object();
    }
     
    class BingB extends Thread {
        public void run(){
            for(int i = 0;i<5;i++){
                //加锁(意思是必须等到本线程的任务代码执行完以后才去执行别的线程的代码)
                synchronized (MyLock.o) {
                    System.out.println("冰冰美,如花丑");
                    MyLock.o.notify();//唤醒另一个线程(这里表示如花线程)
                    try {
                        MyLock.o.wait();//暂时彻底休眠本线程(不会自动唤醒 需要手动唤醒)   同时解锁  阻塞线程 代码就不会往下继续走  jvm会切换到另外一个线程中去
                    catch (InterruptedException e) {
                        // TODO Auto-generated catch block
                    }
                }
            }
        }
    }
     
    class RuH extends Thread{
        public void run(){
            for(int i = 0;i<5;i++){
                synchronized (MyLock.o) {
                    System.out.println("如花美,冰冰丑");
                    MyLock.o.notify();//唤醒另一个线程(这里表示如冰冰程)
                    try {
                        MyLock.o.wait();//暂时彻底休眠本线程   同时解锁  阻塞线程
                    catch (InterruptedException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                }
            }
        }
    }
     
    public class Test {
        public static void main(String[] args) {
            BingB bb = new BingB();
            RuH rh = new RuH();
            bb.start();
            rh.start();
        }
    }

     

    多线程状态流程图:

    写到这里有关线程的基本讲解完毕,如果内容有我自己理解错误的地方还请各位大神指教,小弟不吝求教!

    http://www.q-wei.cn/
    http://news.q-wei.cn/
    http://www.yichaonet.cn/
    http://news.yichaonet.cn/
    http://www.vxjezfv.cn/
    http://news.vxjezfv.cn/
    http://www.xibiyo.com.cn/
    http://news.xibiyo.com.cn/
    http://www.9208361.org.cn/
    http://news.9208361.org.cn/
    http://www.9111316.cn/
    http://news.9111316.cn/
    http://www.bluelf.com.cn/
    http://news.bluelf.com.cn/
    http://www.qqq136com.cn/
    http://news.qqq136com.cn/
    http://www.2819w.cn/
    http://news.2819w.cn/
    http://www.9019758.org.cn/
    http://news.9019758.org.cn/
    http://www.wydaogou.cn/
    http://news.wydaogou.cn/
    http://www.ralhys.cn/
    http://news.ralhys.cn/

    展开全文
  • 并行: 计算机同时执行个任务,并且有个CPU同时来执行这些任务,每个CPU或者线程,都单独执行一个任务,个任务可以在同一时刻同时执行,称为并行,并行只能在核心计算机中实现。 2:进程和线程 进程: 系统...

    1:并发和并行

    并发: 计算机同时执行多个任务,但是多个任务不是同一时刻执行的,而是计算机CPU不断分配时间段给不同的任务,并且快速的切换任务,表面上看起来是同时进行,实际上,同一时间只有一个任务在进行。
    并行: 计算机同时执行多个任务,并且有多个CPU同时来执行这些任务,每个CPU或者线程,都单独执行一个任务,多个任务可以在同一时刻同时执行,称为并行,并行只能在多核心计算机中实现。

    2:进程和线程

    进程: 系统在内存中分配加载进程的内存块,在win系统中执行exe程序,就相当于将当前任务添加到内存块中,即产生一个进程,进程包括一段程序执行的过程和其上下文
    进程独享内存中的一片空间
    线程: 线程共享进程的上下文信息,是进程中更小粒度话的CPU时间片;线程共享进程的内存空间,在jvm中,每个进程都会创建一个栈内存空间,线程独享栈内存空间,线程之间的栈内存互不影响,但是线程之间可以共享进程中的堆内存空间中的数据。

    3:线程的实现方式

    java中线程的实现方式有两种
    ①继承Thread类,重写run方法,然后使用继承的实体对象调用start方法
    Class MyThread extends Thread

    Thread thread = new MyThread();
    thread.start();
    

    ②实体实现Runnable接口,实现run方法,然后创建实体对象,以创建的实体对象去创建Thread类,调用start方法

    Class MyRunnableImpl implements Runnable

    Runnable run = new MyRunnableImpl();
    Thread thread = new Thread(run);
    thread.start();

    使用接口方式实现多线程,可以不影响实现类继续继承其他类,可以共享实现类中数据,实现一个对象多个线程执行,共享对象资源数据。

    4:使用匿名内部类创建线程

    对上面的两种实现线程的方式都可以使用匿名内部类完成:

    new Thread(){
    @override
    run(){
    //业务实现
    }
    }.start();

    new Thread(
    new Runnable(){
    @override
    run(){
    //业务实现
    }
    }
    ).start();

    5:线程的安全问题

    如果多个线程同时访问同一个对象的某个属性,其中某个线程对属性进行修改,将可能造成其他线程访问到的属性信息不一致,从而产生线程的安全性问题。

    6:解决线程的安全问题-线程同步技术

    ①同步代码块
    将可能产生线程安全问题的代码放到代码块中,然后使用synchronized关键字;格式为
    synchronized(锁对象){
    //可能产生线程安全问题的代码块(即访问了共享数据的代码块)
    }

    注意1:锁对象可以是任意对象
    注意2:必须保证多个线程使用的锁对象是同一个对象
    注意3:锁对象的作用:把同步代码块锁住,只允许一个线程在同步代码块中执行
    

    ②同步方法
    将可能产生线程安全的代码,抽取出来定义一个方法,给这个方法加上synchronized修饰符
    事实上和同步代码块一样的功能,即将同步代码块抽出来定义方法,锁对象即为当前对象this
    注意,同步方法可以是静态的,当同步方法是静态的时候,此时的锁对象就不是this了,而是当前类的class对象
    ③lock锁机制
    自JDK1.5之后加入的
    java.utils.concurrent.locks包中的Lock接口,实现类有ReentrantLock
    可以获取到比synchronized更广泛的锁对象;
    使用方法:
    1、在成员位置创建一个ReentrantLock对象
    2、在可能出现安全问题的代码前调用Lock的方法lock获取锁
    3、在可能出现安全问题的代码后调用Lock的方法unlock释放锁;为了保证锁一定会被释放,经常将unlock方法放到try代码块的finally块中执行。

    7:线程同步技术的原理

    	使用了一个锁对象 ,也叫同步锁,也叫对象监视器
    

    多个线程,假如有3个线程t1,t2,t3同时竞争CPU执行权
    当t1抢到了CPU执行权,执行到synchronized代码块的时候,会检查是否有锁对象,如果有锁对象,则执行代码块
    同时t2也在抢夺CPU执行权,如果抢到了,则执行到同步代码块synchronized的时候,也会去检查锁对象,此时锁对象正在被t1占用,于是,t2线程只能继续等待,进入阻塞状态,直到t1线程执行完代码块,归还了锁对象,此时t2检查到了锁对象,才可以执行代码块
    总结: 同步中的线程,没有执行完毕不会释放锁对象,同步外的线程,没有锁进不去同步代码块,保证代码块不会被同时执行
    程序会频繁的检查锁对象,获取锁对象,释放锁对象,降低了效率,保证了安全。

    8:线程的状态

    线程有六种状态:
    new: 新建状态:刚创建的线程,是new状态
    blocked: 阻塞状态:线程调用start后进入竞争CPU,竞争失败,进入阻塞状态,等待再次竞争
    runnable: 运行状态:线程调用start后,进入竞争CPU,竞争成功,即进入运行状态。
    terminated: 死亡状态,线程运行过程出现异常,或者线程run方法执行完毕,进入死亡状态
    timed_watting: 限时等待状态(休眠状态):使用sleep方法或者wait指定时间的方式,使线程退出CPU竞争,等待时间到了之后,或者被唤醒,重新加入竞争CPU
    watting: 无限期等待状态(永久等待状态):使用wait方法使线程进入休眠状态,并且不指定休眠时间,该状态无法主动激活,需等待notify方法唤醒。

    9:等待与唤醒(线程间通信)

    就是wait和notify或者notifyAll

    为了线程之间有效利用CPU资源
    多个线程之间进行,由某一个线程对其中部分资源进行处理,处理完了需要等待另一个线程执行完才可继续工作,则可以使用等待-唤醒机制
    wait和notify 必须是同一个监视器(同一个对象进行调用)

    10:案例:生产者消费者问题

    11:线程池

    线程池的底层:容器:事实上就是集合
    可以使用 ArrayList HashSet HashMap LinkedList等等(List、Set、Map)
    这里使用LinkedList

    JDK1.5之后,内置了线程池对象

    线程池的好处:

    1. 降低资源消耗。减少了创建和销毁线程的次数,每个工作线程都可以被重复利用,可执行多个任务。
    2. 提高响应速度。当任务到达时,任务可以不需要的等到线程创建就能立即执行。
    3. 提高线程的可管理性。可以根据系统的承受能力,调整线程池中工作线线程的数目,防止因为消耗过多的内
      存,而把服务器累趴下(每个线程需要大约1MB内存,线程开的越多,消耗的内存也就越大,最后死机)。

    12:线程池的使用:

    Java里面线程池的顶级接口是 java.util.concurrent.Executor ,但是严格意义上讲 Executor 并不是一个线程池,而只是一个执行线程的工具。真正的线程池接口是java.util.concurrent.ExecutorService 。
    要配置一个线程池是比较复杂的,尤其是对于线程池的原理不是很清楚的情况下,很有可能配置的线程池不是较优的,因此在 java.util.concurrent.Executors 线程工厂类里面提供了一些静态工厂,生成一些常用的线程池。官方建议使用Executors工程类来创建线程池对象。
    Executors类中有个创建线程池的方法如下:
    public static ExecutorService newFixedThreadPool(int nThreads) :返回线程池对象。(创建的是有界线程池,也就是池中的线程个数可以指定最大数量)获取到了一个线程池ExecutorService 对象,那么怎么使用呢,在这里定义了一个使用线程池对象的方法如下:public Future<?> submit(Runnable task) :获取线程池中的某一个线程对象,并执行Future接口:用来记录线程任务执行完毕后产生的结果。线程池创建与使用。
    使用线程池中线程对象的步骤:

    1. 创建线程池对象。
    2. 创建Runnable接口子类对象。(task)
    3. 提交Runnable接口子类对象。(take task)
    4. 关闭线程池(一般不做)。

    Runnable实现类代码:

    public class MyRunnable implements Runnable {
        @Override
        public void run() {
            System.out.println("我要一个教练");
            try {
                Thread.sleep(2000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("教练来了: " + Thread.currentThread().getName());
            System.out.println("教我游泳,交完后,教练回到了游泳池");
        }
    }
    

    线程池测试类:

    public class ThreadPoolDemo {
        public static void main(String[] args) {
            // 创建线程池对象
            ExecutorService service = Executors.newFixedThreadPool(2);//包含2个线程对象
            // 创建Runnable实例对象
            MyRunnable r = new MyRunnable();
            //自己创建线程对象的方式
            // Thread t = new Thread(r);
            // t.start(); ‐‐‐> 调用MyRunnable中的run()
            // 从线程池中获取线程对象,然后调用MyRunnable中的run()
            service.submit(r);
            // 再获取个线程对象,调用MyRunnable中的run()
            service.submit(r);
            service.submit(r);
            // 注意:submit方法调用结束后,程序并不终止,是因为线程池控制了线程的关闭。
            // 将使用完的线程又归还到了线程池中
            // 关闭线程池
            //service.shutdown();
        }
    }
    
    展开全文
  • java多线程系列(一)之java多线程技能 认识cpu、核心与线程 cpu与核心 物理核 物理核数量=cpu数(机子上装的cpu的数量)*每个cpu的核心数 虚拟核 ● 所谓的4核8线程,4核指的是物理核心。通过超线程技术,...
  • Java多线程 进程:一个程序的执行过程叫进程 线程:进程的一条执行路径 多线程:进程的多条执行路径 线程的五种状态 实现方式之一 声明一个类,继承Thread类,重写run()方法,调用类的实例对象的start()方法。 ...
  • 使用多线程技术,可在同一时间内运行不同的任务,使系统的运行效率提高。  一个运行着的程序至少有一个线程在运行,调用public static void main(String[] args)方法的线程是有JVM创建的。 1.2 使用多线程 1.2.1 ...
  • 本题由于共享了一个账户,因此会有线程安全问题,我采用了同步方法保证线程安全。 代码包括账户类,顾客类,银行系统类。代码如下: /* 银行账户类型 */ public class Account { private int balance; //余额 ...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 3,379
精华内容 1,351
关键字:

多线程及线程安全