多线程

  • 1、线程:

  • (1) 线程是程序的最小执行单元

  • (2) 线程之间的关系:交互、互斥、同步

  • (3) 线程创建:构造方法

  • Thread()

  • Thread(String)

  • Thread(Runnable target)

  • Thread(Runnable target,String name)

//创建方式一:
Class ThreadName extends Thread{
    
}

//创建方式二:
class ThreadTest2 implements Runnable{
    
}

//创建方式三:
Thread thread = new Thread();

//创建方式四:
Thread thread = new Thread(String name);

//创建方式五:
Runnable rb = new Runnable();
Thread thread = new Thread(rd);

//创建方式六:
Runnable rb = new Runnable();
Thread thread = new Thread(rd,String name);
  • (4) 方法

void start();   //启动线程
static void sleep(long millis); //线程休眠、毫秒
static void sleep(long millis,int nanos);//休眠
void join();    //使其他线程等待当前线程终止
void join(long millis); //同上
void join(long millis,int nanos);   //同上
static void yield();    //当前运行线程释放处理器资源
static Thread currentThread();  //获取当前线程引用,返回当前运行的线程引用

  • 2、关于线程

  • start()方法来启动线程,真正实现了多线程运行,调用了run()方法;run()方法当作普通方法的方式调用。

  • CyclicBarrier让一组线程等待其他线程;CountDownLatch让一组线程等待某个事件发生。

  • Callable能够抛出checked exception。

  • start()方法让thread进去可运行状态(runnable),等待获取CPU的使用权。

  • 3、线程间的状态转换:

线程状态

      1. 新建(new):新创建了一个线程对象。
      1. 可运行(runnable):线程对象创建后,其他线程(比如main线程)调用了该对象的start()方法。该状态的线程位于可运行线程池中,等待被线程调度选中,获取cpu 的使用权 。
      1. 运行(running):可运行状态(runnable)的线程获得了cpu 时间片(timeslice) ,执行程序代码。
      1. 阻塞(block):阻塞状态是指线程因为某种原因放弃了cpu 使用权,也即让出了cpu timeslice,暂时停止运行。直到线程进入可运行(runnable)状态,才有机会再次获得cpu timeslice 转到运行(running)状态。阻塞的情况分三种:
      • (一). 等待阻塞:运行(running)的线程执行o.wait()方法,JVM会把该线程放入等待队列(waitting queue)中。
      • (二). 同步阻塞:运行(running)的线程在获取对象的同步锁时,若该同步锁被别的线程占用,则JVM会把该线程放入锁池(lock pool)中。
      • (三). 其他阻塞:运行(running)的线程执行Thread.sleep(long ms)或t.join()方法,或者发出了I/O请求时,JVM会把该线程置为阻塞状态。当sleep()状态超时、join()等待线程终止或者超时、或者I/O处理完毕时,线程重新转入可运行(runnable)状态。
      1. 死亡(dead):线程run()、main() 方法执行结束,或者因异常退出了run()方法,则该线程结束生命周期。死亡的线程不可再次复生。
  • Java中sleep方法的几个注意点:

    • Thread.sleep()方法用来暂停线程的执行,将CPU放给线程调度器。
    • Thread.sleep()方法是一个静态方法,它暂停的是当前执行的线程。
    • Java有两种sleep方法,一个只有一个毫秒参数,另一个有毫秒和纳秒两个参数。
    • 与wait方法不同,sleep方法不会释放锁
    • 如果其他的线程中断了一个休眠的线程,sleep方法会抛出Interrupted Exception。
    • 休眠的线程在唤醒之后不保证能获取到CPU,它会先进入就绪态,与其他线程竞争CPU。
    • 有一个易错的地方,当调用t.sleep()的时候,会暂停线程t。这是不对的,因为Thread.sleep是一个静态方法,它会使当前线程而不是线程t进入休眠状态。
  • 4、JDK提供的用于并发编程的同步器:

    • 同步器是一些使线程能够等待另一个线程的对象,允许它们协调动作。
    • 最常用的同步器是CountDownLatchSemaphore,不常用的是BarrierExchanger
  • 5、SimpleDateFormat对象是线程不安全的;

  • 6、TreadLocal

    • 1、ThreadLocal的类声明:
  • public class ThreadLocal可以看出ThreadLocal并没有继承自Thread,也没有实现Runnable接口。所以AB都不对。

    • 2、ThreadLocal类为每一个线程都维护了自己独有的变量拷贝。每个线程都拥有了自己独立的一个变量。
      所以ThreadLocal重要作用并不在于多线程间的数据共享,而是数据的独立,C选项错。
      由于每个线程在访问该变量时,读取和修改的,都是自己独有的那一份变量拷贝,不会被其他线程访问,
      变量被彻底封闭在每个访问的线程中。所以E对。
    • 3、ThreadLocal中定义了一个哈希表用于为每个线程都提供一个变量的副本:
 static class ThreadLocalMap {

        static class Entry extends WeakReference<ThreadLocal> {
            /** The value associated with this ThreadLocal. */
            Object value;

            Entry(ThreadLocal k, Object v) {
                super(k);
                value = v;
            }
        }

        /**
         * The table, resized as necessary.
         * table.length MUST always be a power of two.
         */
        private Entry[] table;
}

原文地址:https://www.cnblogs.com/caoleiCoding/p/8974535.html