java - 多线程

线程 和进程

进程:

进程是程序的基本执行实体

线程:

进程是操作系统能够进行运算调度的最小单位,他被包含在进程之中,是进程中的实际运作单位

  • 并发: 并发: 在同一时刻,又多个指令在单个cpu上交替执行

  • 并行: 并行: 在同一时刻,有多个指令在多个cpu上同时执行

多线程的实现

  1. 继承Thread 该子类赢重写Thread类的run方法 以下是一个简单的例子: 第一步:创建一个Thread的子类,(MyThread) 第二步:在MyThread类里面重写run方法
    @Override
   public void run() {
       for (int i = 0; i < 100; i++) {
           System.out.println(getName()+"你好" +i);
       }
   }

第三步:创建一个MyThread对象,调用start() 方法;

        MyThread myThread = new MyThread();
        MyThread myThread1 =  new MyThread();
        myThread.setName("这是线程1");
        myThread1.setName("这是线程2");
        myThread1.start();
        myThread.start();

运行结果: java - 多线程

  1. 实现Runnable接口的方式进行实现 第一步:自己定义一个类实现Runnable接口(MyRun) 第二步:重写里面的run方法
    @Override
    public void run() {
        for (int i = 0; i < 100; i++) {
            System.out.println("这是线程");
        }
    }

第三步:创建自己的类的对象

 MyRun myRun =new MyRun();

第四部:创建一个Thread类的对象,并开启线程

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

运行结果: java - 多线程 由于MyRun 是实现Runnable的接口 所以不能直接使用getName的方法,如果要用getName方法,首先要用在MyRun类里面调用currentThread 方法; MyRun类:

    @Override
    public void run() {
        for (int i = 0; i < 100; i++) {
            Thread t = Thread.currentThread();
            System.out.println("这是线程"+t.getName());
        }
    }

调用处:

        MyRun myRun =new MyRun();
        Thread thread = new Thread(myRun);
        Thread thread1= new Thread(myRun);
        thread.setName("(线程1)");
        thread1.setName("(线程2)");
        thread.start();
        thread1.start();

运行结果: java - 多线程 2.利用Callable接口和Future接口方式实现 第一步: 创建一个类实现Callable接口(MyCallable) 第二步: 重写call(是有返回值的,表示多线程运行的结果)

    @Override
    public Integer call() throws Exception {
        int sum = 0;
        for (int i = 0; i < 101; i++) {
            sum = sum+i;
        }
        return sum;
    }

第三步:创建MyCallable的对象(表示多线程要执行的任务)

     MyCallable myCallable = new MyCallable();

第四部:创建FutureTask的对象(表示管理多线程运行的结果)

        FutureTask<Integer> futureTask = new FutureTask<>(myCallable);

第五步:创建Thread类的对象,并启动 (表示线程)

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

第六步: 获取结果

        Integer result = futureTask.get();
        System.out.println(result);

运行结果: java - 多线程

线程常见的成员方法

  1. setName():给线程设置名字; 设置名字也可以用构造方法设置一个名字,(子类无法继承父类的构造方法,使用super调用父类的构造方法)

  2. getname (): 获取线程的名字 (注意 如果没有给线程设置名字 线程默认的名字是Thread-0、Thread-1)

  3. setPriority() 设置线程的优先级。数字越大,优先级越高,数字越小,优先级越低。范围为1-10 (默认的优先级是5)

  4. getPriority () 获取线程的优先级(查看线程的优先级,返回的是一个数字) 注意 setPriority 设置的数字越大,代表的是线程抢占到cpu的概率大,优先级越大,并不代表一定先运行完

  5. setDaemon(true); 守护线程 ,把该线程设置成守护线程,如果非守护线程运行结束,那么守护线程会自动停止运行(但不是立刻停止,会继续运行一小段时间。)

  6. 出让线程/礼让线程

  7. 插入线程

线程的生命周期

  1. 新建: 创建线程对象
  2. 就绪:调用start方法之后(有执行权,没有执行资格)
  3. 运行:抢到cpu资源之后(有执行权,有执行资格),如果被其他线程抢走了cpu资源,那么线程会进入到就绪阶段, 如果线程遇到了sleep方法或者其他阻塞方法,则线程进入阻塞阶段,睡眠结束进入就绪状态 阻塞阶段没有执行权,也没有执行资格
  4. 死亡:run方法都执行了,线程死亡

同步 锁:synchronized

    synchronized (){  // 锁对象一定是唯一的
    操作共享数据的代码
    }

例如:电影院有三个窗口卖票,总共卖一百张票 Main类:

        MyThread myThread = new MyThread();
        myThread.setName("窗口1");
        MyThread myThread2 = new MyThread();
        myThread2.setName("窗口2");
        MyThread myThread3 = new MyThread();
        myThread3.setName("窗口3");
        myThread.start();
        myThread2.start();
        myThread3.start();

MyThread类:

     static   int piao = 0;
    @Override
    public void run() {
        while (true){
            if (piao<100){
                try {
                    Thread.sleep(10);
                    piao++;
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
                System.out.println(getName()+"卖出了第" +piao +"票");
            }
        }
    }

此时会导致可能会多卖出票 票数大于100;这个是时候需要加入锁,等上一个线程执行完之后,线程再抢占cpu执行

MyThread加入死锁:此时锁里面的代码是轮流执行的

    static   int piao = 0;
    static Object object  = new Object();
    @Override
    public void run() {
        while (true){
            synchronized (object){
            if (piao<100){
                try {
                    Thread.sleep(10);
                    piao++;
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
                System.out.println(getName()+"卖出了第" +piao +"票");
            }
        }
        }
    }
上一篇:SEO网站优化主要工作内容有什么?
下一篇:SQL注入