欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

JAVA基础---线程学习笔记(一)

程序员文章站 2022-05-22 12:38:33
...

本篇记录线程的基本概念、同步、锁、死锁等

import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.View;

/**
 * 一、概念
 * 进程:是一个正在执行的程序。
 * 每一个进程执行都有一个执行顺序,该顺序是一个执行路径或者叫控制单元
 *
 * 线程:就是进程中的一个独立的控制单元。
 * 线程在控制着进程的执行。
 *
 * 一个进程中至少有一个线程。
 *
 * java vm启动的时候会有一个进程 java.exe
 * 该进程至少有一个线程负责java程序的运行,
 * 这个线程运行的代码是在main方法中。
 * 该线程称之为主线程。
 *
 * 扩展:
 * jvm还会启动垃圾回收线程(gc)
 *--------------------------------------------------------------------------------------
 * 二、创建方式
 * 1、继承Thread类,重写run方法
 *
 * 问题:为什么要重写run呢?
 *
 * Thread用于描述线程。
 * 该类就要定义一个功能来定义线程要运行的代码,这个功能就是run(),目的是存储自定义的代码在线程中运行。
 *
 *
 *
 * start()作用:1)启动线程;
 *              2)调用run方法
 * 问题:为什么不是new ThreadDemo().run()呢?
 * 次写法只是创建了线程并未  启动  然后直接调用run方法。实际上还是在主线程中执行的。
 *
 * 线程是在抢夺cpu的执行权,谁抢到谁执行。
 *
 * 2、实现Runnable接口,重写run方法
 * 步骤:
 *  a定义类实现Runnable接口
 *  b覆盖Runnable接口中的run方法
 *  c将Runnable接口的子类对象当做实际参数传递给Thread类的构造函数
 *  d调用Thread类的start方法开启线程,并调用Runnable接口子类的run方法
 *
 *
 *  问题:两种方式的区别
 *  a实现方式避免了单继承的局限性,一个是继承、一个是实现
 *  b继承Thread类:线程代码存放在Thread类的子类中;实现Runnable线程代码存放在接口子类的run方法中。
 *
 *
 *
 *
 *--------------------------------------------------------------------------------------
 *三、sleep();wait();stop();notify();
 * 图片讲解
 *
 *--------------------------------------------------------------------------------------
 * 四、安全问题
 *  问题原因:当多条语句操作线程共享数据时,一个线程对多条语句只执行了一部分,还没执行完另一个线程就参与进来执行,导致了共享数据的错误。
 *  解决办法:对多条操作共享数据的语句,只能让一个线程执行完。在执行过程中,其他线程不参与运行。
 *              java提供的解决方案:
 *
 *
 *              同步代码块
 *                 synchronized (对象){
                        //需要被同步的代码
                                }
                 对象如同锁,持有锁的线程可以在同步中执行,没有锁的线程即时获取了CPU的执行权,也不能进去,因为没有获取锁。
    同步的前提:
        a必须要有两个或以上的线程执行
        b必须是多个线程使用一个锁
    必须保证同步中只有一个线程在执行

    好处:解决多线程的安全问题。
    坏处:每次都要判断锁,多消耗了资源
 *
 *
 * 同步函数:
 * 同步函数用的锁是哪个?
 * 函数要被对象调用,那么函数都有一个所属对象引用(this)
 * 所以同步函数使用的锁是this
 *
 * 如果同步函数被static修饰后,使用的锁就不是this了,因为静态方法中不可以定义this,
 * 静态进内存时,内存中没有当前类的对象,但是有当前类的字节码文件对象:类名.class   该对象类型是Class
 * 所以静态同步方法使用的锁是该类的字节码文件对象,该对象在内存中是唯一的。
 *
 *
 * --------------------------------------------------------------------------------------
 *
 * 五、应用
 * 单例设计模式
 * 饿汉式
 * class Single{
 *     private static final Single s=new Single();
 *     private Single(){};
 *     public static Single getInstance(){
 *         return s;
 *     }
 * }
 *
 *
 * 懒汉式(解决多线程出现安全问题)
 *  class Single{
 *      private static Single s=null;
 *      private Single(){};
 *      public static Single getInstance(){
 *      if(s==null){//减少判断锁的次数,提高效率
 *          synchronized(Single.class){
 *          if(s==null){
 *              s=new Single();
 *          }
 *      }
 *      }
 *          return s;
 *      }
 *  }
 *
 * --------------------------------------------------------------------------------------
 * 六、死锁
 *同步中嵌套同步,锁却不同
 *示例:ThreadDemo3
 *
 */
public class MainActivity3 extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        ThreadDemo threadDemo=new ThreadDemo("thread_name");
        threadDemo.start();
        findViewById(R.id.tv).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
//                ThreadDemo2 run=new ThreadDemo2();
//                new Thread(run,"thread--------1").start();
//                new Thread(run,"thread--------======2").start();
//                new Thread(run,"thread--------******3").start();

                ThreadDemo3 threadDemo3=new ThreadDemo3();
                new Thread(threadDemo3).start();
                try {
                    Thread.sleep(10);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                threadDemo3.flag=false;
                new Thread(threadDemo3).start();
            }
        });
    }

    class ThreadDemo extends Thread{
        public ThreadDemo(String name) {
            super(name);//设置线程名称
        }

        @Override
        public void run() {
            super.run();
            Log.d("zz",this.getName()+"线程执行了"+(Thread.currentThread().getName()==this.getName()));
        }
    }
    /**
     * 同步函数
     */
    class ThreadDemo2 implements Runnable{
        int count=30;
        Object object=new Object();
        @Override
        public void run() {
            Log.d("zz",Thread.currentThread().getName()+"线程执行了");


                while (true) {
                    todo();
            }


        }

        private synchronized  void todo(){
            if (count > 0) {
                try {
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println(Thread.currentThread().getName() + "执行,当前数量是:===========" + count--);
            }
        }


    }
    /**
     * 死锁代码
     */
    class ThreadDemo3 implements Runnable{
        boolean flag = true;
        @Override
        public void run() {

            if (flag){

                while (true)
                synchronized (MyLock.lock1){
                    System.out.println("if--lock1");
                    synchronized (MyLock.lock2){
                        System.out.println("if--lock2");
                    }
                }
            }else {
                while (true)
                synchronized (MyLock.lock2){
                    System.out.println("else--lock1");
                    synchronized (MyLock.lock1){
                        System.out.println("else--lock2");
                    }
                }
            }
        }
    }

    static class MyLock{
        static Object lock1=new Object();
        static String lock2="lock";
    }

}
JAVA基础---线程学习笔记(一)