java多线程

来源:互联网 发布:自贡汽车票订票软件 编辑:程序博客网 时间:2024/04/30 01:03

线程


【进程概念】指一个内存中运行的应用程序,每个进程都有自己独立的一块内存空间,一个进程可以启动多个线程,

【线程概念】线程总是属于某个进程,进程中的多个线程共享进程的内存。

【分类】用户线程和守候线程。(当所有的用户线程执行完毕的时候,jvm自动关闭,但是守候线程不独立于jvm。一般式由操作系统自己创建的

【常见的方法】

l run()

l start()

l suspend();//不建议使用,当程序挂起后,可通过resume方法唤醒线程。

l interrupt()

l //暂停

l sleep(long millis)(休眠)在指定的毫秒数内让当前正在执行的线程休眠(暂停执行),使用sleep使线程休眠后,只能在设定的时间后使线程处于就绪状态(在线程休眠结束后,线程不一定会马上执行,只是进入了就绪状态,等待着系统进行调度。线程睡眠是帮助所有线程获得运行机会的最好方法。实现了多线程。

l yiled()(让步)暂停当前正在执行的线程对象,并执行其他线程,让步cpu资源。实际中无法保证yield()达到让步目的,因为让步的线程还有可能被线程调度程序再次选中。

wait 导致当前的线程等待,直到其他线程调用此对象的 notify() 方法或 notifyAll() 方法。必须从同步环境内调用wait()notify()notifyAll()方法

Notify唤醒在此对象监视器上等待的单个线程

l join():(合并)t.join()t线程执行完,(将t线程合并到当前线程来,等待t线程结束后再往下执行),相当于方法调 用。

l setPriority(): 更改线程的优先级。1~10与线程休眠类似,线程的优先级仍然无法保障线程的执行次序。只不过,优先级高的线程获取CPU资源的概率较大,优先级低的并非没机会执行。

setDaemon:设置守护线程,使用情况较少,JVM的垃圾回收、内存管理线程都是守护线程

l 终止线程的方法:1、使用退出标志boolean flag

2、使用stop方法强制终止线程(这个方法不推荐使用,因为stop和suspend、resume一样,也可能发生不可预料的结果)。

3.  使用interrupt方法中断线程。

【线程调度】

1、Java线程调度是Java多线程的核心只能最大限度的影响线程执行的次序,而不能做到精准控制。线程休眠的目的是使线程让出CPU的最简单的做法之一,线程休眠时候,会将CPU资源交给其他线程,以便能轮换执行,当休眠一定时间后,线程会苏醒,进入准备状态等待执行。

 

【实现方式】

1、继承java.lang.Thread

2、实现java.lang.Runnable接口

 

----------------------------

【同步与锁】

线程的同步为了防止多个线程访问一个数据对象时,对数据造成的破坏

锁:Java中每个对象都有一个内置锁,,如果一个线程获得该锁,就没有其他线程可以获得锁,直到第一个线程释放(或返回)锁。这也意味着任何其他线程都不能进入该对象上的synchronized方法或代码块,直到该锁被释放。

1、线程同步的目的是为了保护多个线程反问一个资源时对资源的破坏。

2、线程同步方法是通过锁来实现,每个对象都有一个锁,这个锁与一个特定的对象关联,线程一旦获取了对象锁,其他访问该对象的线程就无法再访问该对象的其他同步方法。

3、对于静态同步方法,锁是针对这个类的,锁对象是该类的Class对象。静态和非静态方法的锁互不干预。一个线程获得锁,当在一个同步方法中访问另外对象上的同步方法时,会获取这两个对象锁。

4、对于同步,要时刻清醒在哪个对象上同步,这是关键。

5、编写线程安全的类,需要时刻注意对多个线程竞争访问资源的逻辑和安全做出正确的判断,对“原子”操作做出分析,并保证原子操作期间别的线程无法访问竞争资源。

6、当多个线程等待一个对象锁时,没有获取到锁的线程将发生阻塞。

7、死锁是线程间相互等待锁锁造成的,在实际中发生的概率非常的小。但是,一旦程序发生死锁,程序将死掉

 

【线程安全类】

当一个类已经很好的同步以保护它的数据时,这个类就称为“线程安全的”

【线程死锁】

当两个线程被阻塞,每个线程在等待另一个线程时就发生死锁。 

一个线程启动有了资源A,需要资源B而另外一个线程有了资源B,需要资源A。两者都坚持等待的对方的资源造成死锁。

-----------------------

【线程池】

线程池的基本思想还是一种对象池的思想,开辟一块内存空间,里面存放了众多(未死亡)的线程,池中线程执行调度由池管理器来处理。当有线程任务时,从池中取一个,执行完成后线程对象归池,这样可以避免反复创建线程对象所带来的性能开销,节省了系统的资源。

1、固定大小线程池

2、单任务线程池

3、可变尺寸线程池

4、延迟连接池

5、自定义线程池

  public ThreadPoolExecutor(int corePoolSize,

                              int maximumPoolSize,

                              long keepAliveTime,

                              TimeUnit unit,

                              BlockingQueue<Runnable> workQueue,

                              ThreadFactory threadFactory)

 

【注意】1并不是一启动线程(调用start()方法)就执行这个线程,而是进入就绪状态,什么时候运行要看CPU

2、实现runnable接口这种方法比较好,因为使用接口灵活性好,java是单继承、多实现。如果继承了thread类,就不能再继承其他类了,只能实现接口

3t.interrupt(); 这种结束方式比较粗暴,如果t线程打开了某个资源还没来得及关闭也就是run方法还没有执行完就强制结束线程,会导致资源无法关闭

   t.stop();也是结束某个线程,这种方式比interrupt()更粗暴

4尽管通常采用队列形式,但这是没有保障的。队列形式是指当一个线程完成“一轮”时,它移到可运行队列的尾部等待,直到它最终排队到该队列的前端为止,它才能被再次选中。事实上,我们把它称为可运行池而不是一个可运行队列。

5尽管我们没有无法控制线程调度程序,但可以通过别的方式来影响线程调度的方式。

0 0
原创粉丝点击