• Java并行程序基础。


    并发,就是用多个执行器(线程)来完成一个任务(大任务)来处理业务(提高效率)的方法。而在这个过程中,会涉及到一些问题,所以学的就是解决这些问题的方法。

    线程的基本操作:

      1、创建线程:只需要new一个线程对象即可:Thread myThread=new Thread()。然后 myThread.start() 即可开启线程。那么问题来了,这个线程到底要做些什么呢,所以,Thread有一个run() 方法,方法体则是线程要做的事情。而默认情况下,run()方法什么不做,所以我们需要重写run(),把你要做的事情填进去。

     public static void main(String[] args) {
            Thread t1=new Thread(){
                @Override
                public void run() {
                    System.out.println("hello i am t1");
                }
            };
            t1.start();
        }

      上面使用匿名内部类的方式重写了run方法。

      因为Java是单继承的,有时候继承也是一种稀缺的资源,所以可以用Runable接口来实现:

    public interface Runnable{
            public  abstract void  run();
        }

      Runnable接口就只有一个run方法。

      Thread类还有一个重要的构造方法:public Thread (Runnable target) ,所以,可以通过实现了Runnable接口的类的实力来创建线程,同时,Runnable是一个函数式接口,所以还可以使用Lambda表达式:

    public static void main(String[] args) {
            Thread t1=new Thread(()-> System.out.println("hello i am t1"));
            t1.start();
        }

      2、终止线程:Thread.stop() 可以终止线程,但是它是一个废弃的方法,因为它太过暴力,即使线程正在执行中,也会直接终止,并释放锁。

      3、线程中断:线程中断不会使线程立即退出,而是给线程发送一个通知,告诉目标线程:有人希望你退出啦!至于目标线程如何处理,还是又目标线程自己决定。

            有关线程中断的三个方法:Thread.interrupt() 中断线程。Thread.isInterruputed() 判断是否被中断了。 Thread.interrupted() 判读是否被中断,并且清除中断状态。

     public static void main(String[] args) throws InterruptedException {
            Thread t=new Thread(){
                @Override
                public void run() {
                    while (true)
                        System.out.println("t1 is running.");
                }
            };
            t.start();
            Thread.sleep(1000);
            t.interrupt();
        }

        上面代码中,对线程t进行了中断,但并没有作出中断后的操作,所以是没有效果的。改进:

    public static void main(String[] args) throws InterruptedException {
            Thread t=new Thread(){
                @Override
                public void run() {
                    while (true){
                        if (Thread.currentThread().isInterrupted())
                            break;
                        System.out.println("t1 is running.");
                    }
                }
            };
            t.start();
            Thread.sleep(1000);
            t.interrupt();
        }

      4、等待(wait)和通知(notify):为了支持多线程之间的协作,JDK提供了wait()和notify(),这两个方法并不在Thread类中,而是在Object中,也就是说,任何对象都可以调用这两个方法。

        当线程A 调用了obj.wait()方法后,线程A就会停止执行,转为等待状态。等待的状态要等到其他线程调用obj.notify()方法为止。

        当某个线程调用了object.wait()方法后,该线程就会进去object对象的等待队列。这个等待队列中,可能有多个线程。当调用 object.notify()时,会随机在队列中唤醒一个线程。而调用object.notifyAll()时,会唤醒所有线程。

        注意:wait()和notify()都必须在synchronized语句中,必须先获得目标对象的监听器,才能调用这两个方法。调用wait后,会释放监听器。

      5、挂起(suspend)和继续执行(resume):suspend可以停止线程执行,直到resume。但suspend停止时,不会释放资源,所以不推荐使用。

      6、等待线程结束(join)和谦让(yeild):线程之间协作时,有时会有先后关系,也就是B线程等到A线程执行完了,再执行。

    volatile:

      当用volatile关键字申明变量时,就等于告诉虚拟机,这个变量极有可能会被某些线程修改,虚拟机就会做一些操作,来确保这个变量背修改后,应用程序范围内的所有线程都能看到这个改动。用volatile申明的变量可以保证有序性和可见性,但无法保证原子性。

    守护线程:

      守护线程是一种特殊的线程,它是系统的守护者,在后台完成一些系统性的服务,比如垃圾回收线程。与之对应的是用户线程。当一个Java应用只有守护线程时,Java虚拟机就会自然退出。setDaemon()可以将线程设为守护线程。

    public class test {
      public static class DaemonThread extends Thread{
          @Override
          public void run() {
              while (true){
                  System.out.println("i am alive");
              }
          }
      }
    
        public static void main(String[] args) throws InterruptedException {
            Thread thread=new DaemonThread();
            thread.setDaemon(true);
            thread.start();
            Thread.sleep(2000);
        }
    }

      将thread设置为守护线程,所以在主线程休眠2s后,用户线程全部结束,整个程序也就结束了。

    线程优先级:

      优先级高的线程在竞争资源时,会更有优势。但是这只是概率问题,运气不好的话,高优先级的线程也可能抢占资源失败。setPriority()来设置线程优先级。

    public class test {
        final static Object obj=new Object();
        public static class Low extends Thread{
            static int i=0;
            @Override
            public void run() {
                while (true){
                    synchronized (obj){
                        i++;
                        if (i>100000){
                            System.out.println("low complete。");
                            break;
                        }
                    }
                }
            }
        }
        public static class High extends Thread{
            static int i;
            @Override
            public void run() {
                while (true){
                    synchronized (obj){
                        i++;
                        if (i>150000){
                            System.out.println("high complete.");
                            break;
                        }
                    }
                }
            }
        }
    
        public static void main(String[] args) {
            Thread low=new Low();
            Thread high=new High();
            low.setPriority(Thread.MIN_PRIORITY);
            high.setPriority(Thread.MAX_PRIORITY);
            low.start();
            high.start();
        }
    
    }

      上述代码中,即使high要多加50000次,但是因为优先级高,会更先执行完。

    Synchronized

      关键字synchronized的作用是实现线程间的同步。它的工作是对同步的代码加锁,使得每一次只有一个线程进入同步快,从而保证线程间的安全性。

      用法:可以给指定对象加锁(上面事例中),也可以作用于实例方法:

    public class test implements Runnable {
        static test t=new test();
        static int i=0;
            public synchronized void add(){
                i++;
            }
    
            @Override
            public void run() {
                for (int k=0;k<100000;k++)
                    add();
            }
    
        public static void main(String[] args) throws InterruptedException {
            Thread t1=new Thread(t);
            Thread t2=new Thread(t);
            t1.start();
            t2.start();
            t1.join();t2.join();
            System.out.println(i);
        }
    }
  • 相关阅读:
    23种设计模式-原型模式
    23种设计模式-工厂方法模式
    23种设计模式-代理模式
    23种设计模式-装饰模式
    23种设计模式-策略模式
    CSS高度塌陷问题与解决办法
    Java: 多态
    Java: 接口
    Java: 继承
    Java: 单例设计模式
  • 原文地址:https://www.cnblogs.com/zhangyuhao/p/11552159.html
Copyright © 2020-2023  润新知