Summary 简单总结
类相关
-
域访问权限:
Current Class Same Package Children Other Package public √ √ √ √ protected √ √ √ friendly √ √ private √ 类的访问权限只有
public
和default
两种. -
生成对象时加载顺序
- 若有父类则从父类开始加载
- 静态代码块,静态常量,
- 普通代码块,属性,按照代码顺序执行.
- 构造器
-
对象拷贝
-
深浅拷贝两个对象的区别就是浅拷贝不会拷贝对象中的引用对象,而深拷贝则会拷贝一份对象.
// 浅克隆: class ShallowCopy implements Cloneable{ // 基础类型会拷贝 private int basic = 1; // 引用类型不会拷贝一份全新的. private OtherClass other; void setOtherClass(OtherClass other){ this.other = other; } OtherClass getOtherClass(){ return this.other; } // 需要重写Object的clone()方法. @Override protected Object clone() throws CloneNotSupportedException { return super.clone(); } public String toString() { return "ShallowCopy{" + "basic=" + basic + ", OtherClass=" + cloneTest1 + '}'; } } main(){ ShallowCopy shallowCopy = new ShallowCopy(); shallowCopy.setOtherClass(new OtherClass()); ShallowCopy copyClass = (ShallowCopy) shallowCopy.clone(); System.out.println(shallowCopy.toString()); System.out.println("----"); System.out.println(copyClass.toString()); } /* output: CloneTest1{basic=1, OtherClass=com.javabase.OtherClass@7cd84586} ---- CloneTest1{basic=1, OtherClass=com.javabase.OtherClass@7cd84586}*/
-
深拷贝:
// 深拷贝有两三种方法. // 1. 手动克隆.需要手动赋值,且引用对象也要实现Cloneable class DeepCopy1 implements Cloneable{ private OtherClass otherClass; public OtherClass getOtherClass() { return otherClass; } public void setOtherClass(OtherClass otherClass) { this.otherClass = otherClass; } @Override protected Object clone() throws CloneNotSupportedException { DeepCopy1 deepCopy1 = (DeepCopy1) super.clone(); deepCopy1.setOtherClass((OtherClass) otherClass.clone()); return deepCopy1; } } // 2. 使用序列化进行克隆.本质就是使用序列化把本对象存储到硬盘,然后再读回来. // 也可以使用SerializationUtils的clone(Object obj)方法 { // 将其序列化之后再反序列化,然后再输出. OtherClass otherClass = new OtherClass(); DeepCopy1 deepCopy1 = new DeepCopy1(); deepCopy1.setOtherClass(otherClass); // 尝试序列化 DeepCopy1 deepCopy2; try { ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); ObjectOutputStream objectOutputStream = new ObjectOutputStream(byteArrayOutputStream); objectOutputStream.writeObject(deepCopy1); ObjectInputStream objectInputStream = new ObjectInputStream(new ByteArrayInputStream(byteArrayOutputStream.toByteArray())); deepCopy2 = (DeepCopy1) objectInputStream.readObject(); System.out.println(deepCopy1); System.out.println(deepCopy2); } catch (IOException | ClassNotFoundException e) { e.printStackTrace(); } /* com.javabase.DeepCopy1@5f4da5c3 com.javabase.DeepCopy1@4534b60d*/ // 3. 使用JSON工具.来回转换一下.
-
多线程
-
三种基本方法.
extends Thread
implements Runnable
implements Callable
,这个方法可以返回值.
class ThreadTest implements Runnable{ @Override public void run() { println("hello world"); } } } class ThreadTest implements Callable<String>{ @Override public String call() throws Exception { return "Hello World"; } } main(){ ExecutorService service = Executors.newCachedThreadPool(); for (int i = 0; i < 5; i++) { // Callable使用submit.Runnable使用execute. Future<String> futureTask = service.submit(new ThreadTest()); System.out.println(futureTask.get()); } }
-
处理异常
-
由于线程的特殊性线程无法捕捉到抛出到Run外部的异常,所以要么在
Run
方法内部就把异常处理完,要么就设置一个可以处理这种异常的类class testT implements Runnable{ @Override public void run(){ // 这个线程总是会抛出异常,抛出的异常即使是在try catch块里面也捕捉不到 throw new RuntimeException; } }
-
解决方法一:
Thread.currentThread().setUncaughtExceptionHandler()
,如果只是单纯的执行new Thread.strat;这种方法是没有问题的,但是如果将线程交给线程池来执行的话,可能会发生仍然捕获不到错误的异常.原因public void run() { Thread.currentThread().setUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() { @Override public void uncaughtException(Thread t, Throwable e) { System.out.println(t.getName() + "\t" + e.toString()); } }); } // 写在run方法里有效,写在构造器内无效,猜测还是因为线程池创造的线程会代为执行run方法,所以才会有效.
-
解决方法二:重写
ThreadFactory
,这是书本上讲的方法,在初始化线程池的时候创建一个能够为每个线程设置Handler的FactoryExecutorService service = Executors.newCachedThreadPool(new ThreadFactory() { @Override public Thread newThread(Runnable r) { Thread t = new Thread(r); t.setUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() { @Override public void uncaughtException(Thread t, Throwable e) { System.out.println(t.getName() + "\t" + e.toString()); } }); } });
-
1
-
-
同步的方法
-
synchronized
内建字段 -
显式的
lock
方法.class LockTest { private int value; tested(int value) { this.value = value; } Lock lock = new ReentrantLock(); void setValue() { try { locked = lock.tryLock(1000, TimeUnit.MILLISECONDS); this.value += 1; Thread.yield(); this.value += 1; System.out.println(this.value); } catch (InterruptedException e) { System.out.println(locked); } finally { lock.unlock(); } } }
-
同步方法块
-
同步方法块可以有效减少线程占用方法的时间,效率更高.
-
synchronized(Object object)
方法,一般synchronized(this)
即锁定当前对象就是合适的做法,但也可以尝试锁定其他对象. -
Lock
同步代码块void syncBlock1(){ synchronized(this){ // do Something } // do Something } void syncBlock2(){ lock.lock(); try{ // do something }finally{ lock.unlock(); } // do something }
-
-
ThreadLocal
class tested { ThreadLocal<Integer> local = new ThreadLocal<>() { @Override protected Integer initialValue() { int a = new Random().nextInt(10); System.out.println(Thread.currentThread().getName() + "\t initial\t" + a); return a; } }; void increase(){ this.local.set(local.get()+1); Thread.yield(); this.local.set(local.get()+1); System.out.println(Thread.currentThread().getName()+"\t"+this.local.get()); } void getValue(){ System.out.println(this.local.get()); } } class ThreadTest implements Runnable { private tested t; public ThreadTest(tested t) { this.t = t; } @Override public void run() { t.increase(); // t.getValue(); } } main(){ ExecutorService service = Executors.newCachedThreadPool(); tested t= new tested(); for (int i = 0; i < 5; i++) { service.execute(new ThreadTest(t)); } service.shutdown(); }
在被共享的对象内部使用
ThreadLocal
类,这样就会为每一个线程都创建一个自己独有的资源.其他线程无法访问. ThreadLocal原理
-
-
线程的中断
-
Thread.interrupt()
;class ThreadTest implements Runnable { @Override public void run() { System.out.println("test Thread running, ready to sleep"); try { Thread.sleep(1000); } catch (InterruptedException e) { System.out.println("test Thread is interrupted"); e.printStackTrace(); } } } main(){ Thread t1 = new Thread(new ThreadTest()); t1.start(); TimeUnit.MILLISECONDS.sleep(100); t1.interrupt(); } /* output: test Thread running, ready to sleep test Thread is interrupted java.lang.InterruptedException: sleep interrupted at java.base/java.lang.Thread.sleep(Native Method) at com.javabase.ThreadTest.run(TestDog.java:53) at java.base/java.lang.Thread.run(Thread.java:830) */
-
线程池中断
// Sleep可以中断,IO和同步,都不可以中断 // 使用线程池的submit进行中断. Future<?> future = service.submit(new ThreadTest(t)); TimeUnit.MILLISECONDS.sleep(100); future.cancel(true);
-
书中只简单的介绍了两种中断的方法.
-
-
线程的协调工作.
wait,notify,notifyAll
都必须放在同步的代码块里面来执行.即线程只有在已经获得锁的情况下来执行对锁的操作.
-
1