zoukankan      html  css  js  c++  java
  • Java多线程学习笔记(一)——多线程实现和安全问题

    1. 线程、进程、多线程:

    进程是正在执行的程序,线程是进程中的代码执行,多线程就是在一个进程中有多个线程同时执行不同的任务,就像QQ,既可以开视频,又可以同时打字聊天。

    2.线程的特点:

    1.运行任何一个java程序,jvm在运行时都会创建一个main线程来执行main方法。

    2.一个java应用程序至少有两个线程,一个是主线程,负责main方法的执行,一个是垃圾回收器线程,负责回收垃圾。

    3.我们可以利用Thread.currentThread().getName()获得当前线程名字。

    3.多线程的优点:

    1.可以同时处理多个任务。

    2.提高资源的利用率。

    缺点:

    1.增加了CPU负担,因为CPU要不断的来回切换。

    2.降低了一个进程中线程的执行概率。

    3.存在线程安全问题。

    4.会发生死锁现象。

    4.如何创建一个线程:

    方式一:  1.自定义一个类继承Thread类;

          2.重写Thread类中的run方法(自定义线程的任务代码就放在run方法里);

                 3.创建Thread子类的对象,并且调用start方法开启线程。(run方法不能直接调用)

    class Demo extends Thread{
        
        public void run(){    //重写run方法
            for(int i=0;i<100;i++){
                System.out.println("自定义线程"+i)
    
            }
    
        }
    
        public static void main(String[] args){
    
             Demo d = new Demo();
             d.start();   //调用start方法开启线程
             
             for(int i=0;i<100;i++){  
                System.out.println("main线程"+i)
    
            }
        }
    
    
    }

    方式二:实现Runnable接口,Thread类中有构造方法,可以传递Runnable实例。

    class Demo1 implements Runnable{
        
        public void run(){    //重写run方法
            for(int i=0;i<100;i++){
                System.out.println("自定义线程"+i)
    
            }
    
        }
    
        public static void main(String[] args){
    
             Demo d = new Demo();
             Thread thread = new Thread(d);
             thread .start();   //调用start方法开启线程
             
             for(int i=0;i<100;i++){  
                System.out.println("main线程"+i)
    
            }
        }
    
    
    }

    方式三:实现Callable接口

    * Callable是类似于Runnable的接口,实现Callable接口的类和实现Runnable的类都是可被其它线程执行的任务。

    * Callable和Runnable有几点不同:

    * (1)Callable规定的方法是call(),而Runnable规定的方法是run().

    * (2)Callable的任务执行后可返回值,而Runnable的任务是不能返回值的。

    * (3)call()方法可抛出异常,而run()方法是不能抛出异常的。

    * (4)运行Callable任务可拿到一个Future对象,

    * Future 表示异步计算的结果。它提供了检查计算是否完成的方法,以等待计算的完成,并检索计算的结果。

    * 通过Future对象可了解任务执行情况,可取消任务的执行,还可获取任务执行的结果。

    实现代码:

    package xiancheng.callable;
    
    import java.util.concurrent.Callable;
    
    public class MyCallable implements Callable<Integer>{
    
        @Override
        public Integer call() throws Exception {
            int sum = 0;
            for(int i = 0;i<10;i++){
                sum+=i;
            }
            return sum;
        }
    }
    public class CallableTest {
        
        public static void main(String[] args) throws Exception{
            /*// 第一种方式:通过线程池来获取线程
            ExecutorService executor = Executors.newCachedThreadPool();//创建线程池
            Future<Integer> future = executor.submit(new MyCallable());//ExecutorService中的submit方法接受一个Runnable或者Callable,然后返回一个Future来获得任务的执行结果或者取消任务。
            System.out.println("result:" + future.get());
            executor.shutdown();*/
            
            //第二种方式
            MyCallable mc = new MyCallable();
            FutureTask<Integer> futureTask = new FutureTask<Integer>(mc);        
            Thread thread = new Thread(futureTask);
            thread.start();
            System.out.println("result:" + futureTask.get());
        }
    
    }

    结果为:result:45

    Executors、ExecutorService介绍请移步Java多线程学习笔记(二)——Executor,Executors,ExecutorService比较

    Future、FutureTask介绍请移步Java多线程学习笔记(三)——Future和FutureTask

    5.实例变量与线程安全

    场景一:数据不共享情况

    public class MyThread extends Thread{
        private int i = 5;
        public MyThread(String s){
            super();
            this.setName(s);
        }
        
        public void run(){
            super.run();
            while(i>0){
                i--;
                System.out.println("由"+Thread.currentThread().getName()+"计算i="+i);
            }
        }
    }
    public class Run {
        
        public static void main(String[] args) {
            MyThread a = new MyThread("A");
            MyThread b = new MyThread("B");
            MyThread c = new MyThread("C");
            a.start();
            b.start();
            c.start();
        }
    
    }

    运行结果:

     

    我们创建三个独立的线程,每个线程有自己的变量。不会出现安全问题。

    场景二:五个售票员卖票

    public class MyThread extends Thread{
        private int i = 5;
        public void run(){
            super.run();
            i--;
            System.out.println("由"+Thread.currentThread().getName()+"计算i="+i);    
        }
    }
    public class Run {    
        public static void main(String[] args) {
            MyThread myThread = new MyThread();
            Thread a = new Thread(myThread,"A");
            Thread b = new Thread(myThread,"B");
            Thread c = new Thread(myThread,"C");
            Thread d = new Thread(myThread,"D");
            Thread e = new Thread(myThread,"E");
            
            a.start();
            b.start();
            c.start();
            d.start();
            e.start();
        }
    }
     
    运行结果:
     
    线程A,C,B打印出相同的数字,说明产生了线程安全问题,我们想要的结果是递减的。
    解决方法:
    public class MyThread extends Thread{
        private int i = 5;
        synchronized public void run(){
            super.run();
            i--;
            System.out.println("由"+Thread.currentThread().getName()+"计算i="+i);    
        }
    }

    运行结果:

    由A计算i=4
    由D计算i=3
    由C计算i=2
    由B计算i=1
    由E计算i=0

     6.线程生命周期:

    1.创建阶段:当创建线程的继承类时就实现这一阶段。new Demo();

    2.可运行阶段:当调用start方法时。

    3.运行状态:线程拿到CPU执行权时。当执行权被夺走时又会回到可运行阶段。

    4.临时阻塞状态:是线程因为某种原因放弃CPU使用权,暂时停止运行。直到线程进入可运行阶段,才有机会转到运行状态。

    临时阻塞状态又分为三种:

             1)等待阻塞:运行的线程执行wait()方法,JVM会把该线程放入等待池中。
             2)同步阻塞:运行的线程在获取对象的同步锁时,若该同步锁被别的线程占用,则JVM会把该线程放入锁池中。
             3)其他阻塞:运行的线程执行sleep()或join()方法,或者发出了I/O请求时,JVM会把该线程置为阻塞状态。当sleep()状态超时、join()等待线程终止或者超时、或者I/O处理完毕时,线程重新转入可运行状态。

    5.死亡状态:线程执行完了或者因异常退出了run()方法,该线程结束生命周期。

  • 相关阅读:
    常用sql
    epoll
    poll
    ShardedJedis的分片原理
    puppet(一种Linux、Unix、windows平台的集中配置管理系统)
    zabbix(一个基于WEB界面的提供分布式系统监视以及网络监视功能的企业级的开源解决方案)
    1111
    http_load(基于linux平台的一种性能测试工具)
    zenoss(智能监控软件)
    SaltStack(自动化运维工具)
  • 原文地址:https://www.cnblogs.com/love-Stefanie/p/6706507.html
Copyright © 2011-2022 走看看