Java中的多线程是一种抢占机制而不是分时机制。抢占机制指的是有多个线程处于可运行状态,但是只允许一个线程在运行,他们通过竞争的方式抢占CPU。
java中多线程的实现方法主要由两种:
继承 Thread 类实现runnable接口
但实际开发中主要以2为主,因为实现接口优势有:
可以避免由于 Java 的单继承特性而带来的局限;
增强程序的健壮性,代码能够被多个线程共享,代码与数据是独立的;适合多个相同程序代码的线程区处理同一资源的情况。线程的状态: 新生状态(new):当一个线程被new的时候,其处于新生状态,被分配内存,但该线程没有运行,不是活的(not alive);
就绪状态(runnable):调用线程实例的start()方法进入就绪状态,但还没有被分配到cpu执行,只是进入线程队列,等待系统将其分配给cpu,等待状态并不是执行状态,此时是活的;
执行状态(running):一旦获取cpu,即进入运行状态,线程的run()开始执行。期间可能被 因为调用其他方法而结束;等待某种资源而阻塞;完成任务而死亡;在指定时间内没有结束因而被替换到线程的等待状态(此时是活的);
阻塞状态(blocked):通过调用join()\wait()\sleep()或者资源被暂用使线程处于bolcked状态,此时线程仍然是活的
死亡状态(dead):当一个线程的run()方法执行完毕或被中断或者因异常退出,则进入死亡状态。
——-更新线———– 2017.7.5更新 随着了解的深入,对线程的认识更加深入了些 new一个线程的方式有new thread 和 implement runnable,这两者都要重写run()方法,run方法就是新任务的执行方法体了,但该方法本身不会触发线程了,当Thread.start()时该线程才会创建出来,然后就是就绪,获得CPU时间后才进入run()方法,执行任务。当然在执行过程中,可以人为设置睡眠,Thread.currentThread().sleep(milseconds),进入睡眠会交出cpu执行机会给别的线程,自身进入阻塞状态,当然之前假如获得了锁则不会释放,睡眠时间到了并不会直接获得cpu执行机会,因为它在阻塞状态—>就绪状态;当然当前运行的thread还可以调用yeild()方法。即Thread.currentThread().yield(),这样当前thread也会让出cpu执行时间给别的线程,同样不会释放之前获得的锁,自身会进入就绪状态,当机会合适立即重新执行;当前线程还可以调用join()方法,即new thread1().join(),则会让当前线程进入等待状态,直到thread1执行完毕(不管thread1中是否有sleep/yield)
1、Spring中使用ThreadLocal解决线程安全问题 2、servlet会给不同的请求创建一个thread,而bean的创建是单例模式,因此就是多个线程操作一个单例的场景 3、解决单例模式下的线程安全问题常用的是同步机制及ThreadLocal 二者区别: 同步机制是以时间换空间,即使用同步锁将共享变量锁住,同一时间只能一个线程对其访问并修改 ThreadLocal是以空间换时间,为每一个线程都提供一份变量副本,因此可以同时访问互不影响(这里有一点感觉很有必要:当涉及对全局变量的修改时,比如count++,应该使用同步锁机制,保证count对所有线程都是一致的) 4、线程安全都是由全局变量及静态变量引起的,若所有的线程对全局变量或静态变量读操作不会有安全问题,涉及写操作时会有安全问题 5、局部变量是线程安全的 6、Spring中避免出现线程安全问题的解决方式: 6.1 scope为protoType,每次请求过来映射到实例都会创建新的 6.2 避免出现全局变量,变量都写到方法内,方法内变量都是线程安全的
