一、线程与进程的区别
1、进程是作为资源分配的单位;线程是调度和执行的单位。
2、进程有独立的代码和数据空间(上下文),切换开销大;线程可以看做未轻量级进程,同一类线程共享代码和数据空间,每个线程有独立的运行栈和程序计数器,切换开销小。
3、系统在运行时为每个进程分配不同的内存区域;除CPU以外,不会为线程分配内存(线程所使用的资源是它所属的进程的资源)
二、Java线程实现
1、直接继承Thread,实现run接口。
public class ThreadTest extends Thread { @Override public void run() { super.run(); } }
2、使用静态代理模式,new Thread增加Runable的实现类(推荐方案,可以实现复用和解耦)
public class ThreadTest { public static void main(){ Thread thread = new Thread(new RunableTest(),"测试线程"); thread.start(); } } class RunableTest implements Runnable{ @Override public void run() { } }3、使用Callable接口,使线程可以抛异常和返回数据。public class CallableThreadTest { public static void main(String[] args) throws ExecutionException, InterruptedException { ExecutorService service = Executors.newFixedThreadPool(1); Race race1 = new Race("乌龟",1000); Race race2 = new Race("兔子",500); Future<Integer> result1 = service.submit(race1); Future<Integer> result2 = service.submit(race2); Thread.sleep(2000); int raceresult1 = result1.get(); int raceresult2 = result2.get(); service.shutdown(); } } /** * Callble 可以声明异常和跑出异常 */ class Race implements Callable<Integer>{ private String name;//名称 private long time;//时长 private Integer step=0;//步数 private Boolean flag=true;//标志位 public Race(String name, long time) { this.name = name; this.time = time; } @Override public Integer call() throws Exception { while (flag){ step++; Thread.sleep(time); } return step; } }
三、线程同步(线程安全):
1、synchronized 同步块(引用类型|this|类.class)
2、synchronized 同步方法
/** * 单例设计模式 * 确保一个类只有一个对象 * 懒汉式 * 1、构造器私有化,避免外部创建对象 * 2、声明一个私有的静态变量 * 3、创建一个对外的公共的静态方法访问变量,如果变量没有值,则赋值。 */ class SyncTest{ private static SyncTest instance = null; private SyncTest() { } //锁定方法 public static synchronized SyncTest getInstance(){ if (null == instance){ instance = new SyncTest(); } return instance; } //锁定类的字节码信息---效率不高,对象存在也需要等待 public static SyncTest getInstance2() { synchronized (SyncTest.class) { if (null == instance) { instance = new SyncTest(); } return instance; } } //先判断对象是否为空。 dubbo check 双重检查 public static SyncTest getInstance3() { if (null == instance) { synchronized (SyncTest.class) { if (null == instance) { instance = new SyncTest(); } } } return instance; } } /** * 单例设计模式 * 饿汉式--类使用时即刻初始化 * 1、构造器私有化,避免外部创建对象 * 2、声明一个私有的静态变量并初始化 * 3、创建一个对外的公共的静态方法访问变量。 */ class SyncDemo2{ private static SyncDemo2 instance= new SyncDemo2(); private SyncDemo2() { } public static SyncDemo2 getInstance(){ return instance; } } /** * 单例设计模式 * 饿汉式-优化版-getInstnce初始化 * 1、构造器私有化,避免外部创建对象 * 2、声明一个私有的静态变量并初始化 * 3、创建一个对外的公共的静态方法访问变量。 */ class SyncDemo3{ private static class Holder { private static SyncDemo3 instance = new SyncDemo3(); } private SyncDemo3() { } public static SyncDemo3 getInstance(){ return Holder.instance; } }
转载内容:补充记忆:
1、synchronized关键字的作用域有二种:1)是某个对象实例内,synchronized aMethod(){}可以防止多个线程同时访问这个对象的synchronized方法(如果一个对象有多个synchronized方法,只要一个线程访问了其中的一个synchronized方法,其它线程不能同时访问这个对象中任何一个synchronized方法)。这时,不同的对象实例的synchronized方法是不相干扰的。也就是说,其它线程照样可以同时访问相同类的另一个对象实例中的synchronized方法;2)是某个类的范围,synchronized static aStaticMethod{}防止多个线程中不同的实例对象(或者同一个实例对象)同时访问这个类中的synchronized static 方法。它可以对类的所有对象实例起作用。
2、除了方法前用synchronized关键字,synchronized关键字还可以用于方法中的某个区块中,表示只对这个区块的资源实行互斥访问。用法是: synchronized(this){/*区块*/}(或者synchronized(obj){/*区块*/}),它的作用域是当前对象;
3、synchronized关键字是不能继承的,也就是说,基类的方法synchronized f(){} 在继承类中并不自动是synchronized f(){},而是变成了f(){}。继承类需要你显式的指定它的某个方法为synchronized方法;