标签:div package utils 实现类 cep 管理所 自动 不同 创建
进程是一个相对独立的执行单位。
进程的一部分,进程中实际的任务执行者,必须依附于进程。线程对进程的依赖主要体现在:
线程与进程是两个相对的概念,一个对象相对于它拥有的执行单位被称为进程,从自身所属的上级执行者来看,又被称作线程。
CUP在任何一个时间点都只能执行一个线程,多线程的本质是多个任务高速交替执行。如果多个线程间不存在数据交换,可以单独执行,采用多线程并不能减少总的执行时间。
多线程设计的主要目的不是为了提高执行速度,而是相对平均地执行每一个线程,不致使某一个线程长时间持有CPU时间片,其他线程长时间处于等待状态。由于CPU时间片在多个线程间切换迅速,超出了人类感官所能察觉的范围,所以感觉多个任务都是执行。
例如,当多个人访问同一个网站,每一个人都需要5分钟,如果不采用多线程,同时只允许一个人进入网站,其他多数人都要等待5分钟,用户体验很差。这是采用多线程,一个人进入以后,CPU转向其他用户,让其他用户陆续进入,用户体验就提高了,尽管总的执行时间并没有减少。
⑴Java采用单继承,即一个类只能继承一个父类,而允许一个类实现多个接口,采用继承Thread的方式创建线程,就使本类失去了唯一的一次继承机会。
4.采用实现Runnable接口的方式创建线程,不仅保留了唯一的继承机会,而且在实现资源共享的操作相对简单,所以一般采用该方式创建线程。
提供共享资源的外部类
package com.test.thread.extendsThread; public class MyClass { public int count; }
Thread线程子类
package com.test.thread.extendsThread; public class MyThread extends Thread { private MyClass obj; public MyThread() { super(); } public MyThread(MyClass obj) { super(); this.obj = obj; } @Override public void run() { System.out.println("obj=" + obj); while (true) { synchronized (obj) { if (obj.count > 0) { try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName() + "----当前数量=" + obj.count--); } else return; } } } }
测试类
package com.test.thread.extendsThread; import org.junit.Test; import com.test.thread.synchronizedTest.demo02.MyTestRunnable; import net.sourceforge.groboutils.junit.v1.MultiThreadedTestRunner; import net.sourceforge.groboutils.junit.v1.TestRunnable; public class ThreadExtendsTest { /** * JUnit单元测试不支持多线程测试,使用GroboUtils进行多线程测试(导入架包) * * @throws Throwable */ @Test public void test01() throws Throwable { MyClass obj = new MyClass(); obj.count = 10; MyThread myth01 = new MyThread(obj); MyThread myth02 = new MyThread(obj); MyThread myth03 = new MyThread(obj); MyTestRunnable t01 = new MyTestRunnable(myth01); MyTestRunnable t02 = new MyTestRunnable(myth02); MyTestRunnable t03 = new MyTestRunnable(myth03); TestRunnable[] tr = new TestRunnable[3]; tr[0] = t01; tr[1] = t02; tr[2] = t03; MultiThreadedTestRunner mttr = new MultiThreadedTestRunner(tr); mttr.runTestRunnables(); } // 放在主线程中测试 public static void main(String[] args) { MyClass obj = new MyClass(); obj.count = 10; MyThread t01 = new MyThread(obj); MyThread t02 = new MyThread(obj); MyThread t03 = new MyThread(obj); t01.setName("t01"); t02.setName("t02"); t03.setName("t03"); t01.start(); t02.start(); t03.start(); } }
由不同阶段构成的线程从出生到死亡的整个过程,叫做线程的生命周期。
了解线程的生命周期能够更好地掌握线程的运行情况,比如线程的就绪状态,意味着不是调用start方法之后,线程立即执行。
一个线程A在另一个线程B内部调用join方法,B线程中止,A线程开始执行,A线程执行完毕,B线程才开始执行。
线程优先级设定了线程获取CPU时间片的概率,仅仅是一种概率,不能保证优先级高的线程一定优先获得CPU时间片。
线程优先级分为10个等级,从1-10,数值越大,优先级越高,通过setProprity(int)方法设置。
Thread.yield,线程礼让只是通知当前线程可以将资源礼让给其他线程,并不能保证当前线程一定让出资源。
使得同一资源同一时刻只能有一个线程访问的安全机制,即一个线程访问完毕,其他线程才能访问。
由于目标资源同一时刻只有一个线程访问,解决了线程安全问题。
synchronized(共享对象){ 修改共享数据的代码 }
上述代码给修改共享数据的代码加了一个对象锁。任何一个对象只有一把对象锁,只有获得了对象才能访问加锁的资源。一个线程获取了对象锁,执行加锁的代码,执行完毕,归还对象锁,其他获取对象锁的线程才可以执行加锁的代码。
synchronized关键字加到静态方法上时,形成类锁,执行该方法上必须获取类锁。
类锁与对象锁是两种不同的锁,允许一个线程持有类锁,另一个线程持有对象锁。
synchronized关键字加在成员方法,该方法成为同步成员方法,由于一个对象只有一把对象锁,一个线程访问了一个同步成员方法,其他线程不能访问其他同步成员方法。
同步方法不可以被继承,同步方法在子类中失去同步机制。
在同步机制中,如果同步代码的执行需要满足一定条件,那么将判断条件放在锁内,保证当前获取了锁的线程在执行同步代码时满足执行条件。如果放在锁外,有可能出现当前线程获取了锁以后不满足执行条件的情况。
public void run() { System.out.println("obj=" + obj); while (true) { synchronized (obj) { if (obj.count > 0) { try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName() + "----当前数量=" + obj.count--); } else return; } } }
线程A需要多把锁,线程B持有A缺少的锁,缺少A持有的锁,由于线程在获取到全部的锁之前不会释放持有的锁,这使得线程A与线程B陷入僵持,整个进程处于停滞状态。
减少同步机制中锁的数目,尽量避免同一把锁出现在多处。
一般情况下创建的线程都是用户线程,即该线程未被显式设定为守护线程,未在守护线程内部创建。
运行在后台、为用户线程提供服务的线程。
用户线程调用setDaemon(true)方法,或者在守护线程内部创建线程。
守护线程用于为用户线程提供服务,如垃圾回收器。
1.线程局部变量,为每一个线程提供一个变量的副本,使得各个线程相对独立地操作变量,避免线程安全问题。
2.首先必须明确一点,ThreadLocal.get()获取的变量副本必须手动传入:
ThreadLocal.set(Object obj)
初次获取时,判断线程局部变量中是否保存有变量副本,如果没有则手动传入,在该线程中下次获取的就是初次传入的对象。
3.ThreadLocal的目的是保证在一个线程内部,一次创建,多次获取。
4.基本原理:
将初次传入的变量与线程绑定,线程不变,变量不变。
⑴继承TestRunnable,实现其中的抽象方法runTest,将需要运行的代码放入该方法中。通常为子类定义一个有参构造方法,方法形参为需要测试的线程,在runTest方法中调用测试线程的run方法,从而将将需要执行的代码注入runTest方法中。
TestRunnable[] tr=new TestRunnable[len];
MultiThreadedTestRunner mttr=new MultiThreadedTestRunner(tr); mttr.runTestRunnables();
标签:div package utils 实现类 cep 管理所 自动 不同 创建
原文地址:http://www.cnblogs.com/tonghun/p/6935659.html