`

record

 
阅读更多

子类是不继承父类的构造器(构造方法或者构造函数)的,它只是调用(隐式或显式)。如果父类的构造器带有参数,则必须在子类的构造器中显式地通过 super 关键字调用父类的构造器并配以适当的参数列表。

如果父类构造器没有参数,则在子类的构造器中不需要使用 super 关键字调用父类构造器,系统会自动调用父类的无参构造器。

java关键字Transient

    Java的serialization提供了一种持久化对象实例的机制。当持久化对象时,可能有一个特殊的对象数据成员,我们不想用serialization机制来保存它。为了在一个特定对象的一个域上关闭serialization,可以在这个域前加上关键字transient。   

    transient是Java语言的关键字,用来表示一个域不是该对象串行化的一部分。当一个对象被串行化的时候,transient型变量的值不包括在串行化的表示中,然而非transient型的变量是被包括进去的。

 

2. Java静态方法

静态方法属于类,而不属于类的对象。

可以直接调用静态方法,而无需创建类的实例。

静态方法可以访问静态数据成员,并可以更改静态数据成员的值。

 

静态方法的限制

静态方法有两个主要限制。它们分别是:

 

静态方法不能直接使用非静态数据成员或调用非静态方法。

this和super两个关键字不能在静态上下文中使用。

 

为什么java main方法是静态的?

这是因为对象不需要调用静态方法,如果它是非静态方法,jvm首先要创建对象,然后调用main()方法,这将导致额外的内存分配的问题。

 

在java中,只通过改变方法的返回类型来实现方法重载是不可能的,因为这样具有模糊性

 

List 循环移动元素

 public static void main(String[] args) {

      List list = Arrays.asList("one Two three Four five six".split(" "));

      System.out.println("List :"+list);

      Collections.rotate(list, 3);

      System.out.println("rotate: " + list);

   }

 

 线程的让步使用Thread.yield()方法,yield()为静态方法,功能是暂停当前正在执行的线程对象,并执行其他线程。

 

 追其同步的根本的目的,是控制竞争资源的正确的访问,因此只要在访问竞争资源的时候保证同一时刻只能一个线程访问即可,因此Java引入了同步代码快的策略,以提高性能。

 

  开发过程中很让人头疼的就是各种类型之间的转换,一开始真是蒙圈,后来用了几次好点了,赶紧把自己记得的写下来,怕以后忘了。

 

一、JASSONArray转为JSONObject

 

       JSONArray result_type = new JSONArray();

 

       StringBuffer cdsIdxType = new StringBuffer();

 

       cdsIdxType.append(" select id from table_type ");

 

       result_type = jdbcTemp.queryForJSONArray(cdsIdxType.toString());

 

      JSONObject jsonObject = (JSONObject) result_type.get(i);

 

二、JASONArray转为List

 

      JSONArray result_type = new JSONArray();

 

 

       StringBuffer cdsIdxType = new StringBuffer();

 

 

       cdsIdxType.append(" select id from table_type ");

 

 

       result_type = jdbcTemp.queryForJSONArray(cdsIdxType.toString());

 

 

       ArrayList list_type = new ArrayList();

 

 

       for (int i = 0; i < result_type.size(); i++) {

 

 

        JSONObject jsonObject = (JSONObject) result_type.get(i);

 

 

        list_type.add(jsonObject.get("id"));

 

 

       }

 

 

 

三、JSONArray转为String

 

      

 

       JSONArray result_type = new JSONArray();

 

 

       StringBuffer cdsIdxType = new StringBuffer();

 

 

        cdsIdxType.append(" select id from table_type ");

 

 

       result_type = jdbcTemp.queryForJSONArray(cdsIdxType.toString());

 

 

       String typeAll = "";

 

 

       ArrayList list_type = new ArrayList();

 

 

       for (int i = 0; i < result_type.size(); i++) {

 

 

        JSONObject jsonObject = (JSONObject) result_type.get(i);

 

 

        list_type.add(jsonObject.get("id"));

       

       }

 

 

       for(int j=0;j<list_type.size();j++){

 

 

        typeAll = typeAll + "'" + list_type.get(j) + "'" + ",";

 

 

       }

 

 

       typeAll = typeAll.substring(0, typeAll.length() -1);

 

四、String转换为ArrayList

 

     String tablecode = request.getParameter("tablecode");

 

 

      tablecode = tablecode.substring(1, tablecode.length()-1).replace("\"", "");

 

 

      String[] list = tablecode.split(",");

 

 

      ArrayList tables = new ArrayList();

 

 

      for(int i=0; i<list.length; i++){

 

 

       tables.add(list[i]);

 

 

      }

 

五.String转JSONObject

 

String jsonMese = "{\"语文\":\"88\",\"数学\":\"78\",\"计算机\":\"99\"}";

 

JSONObject  myJson = JSONObject.fromObject(jsonMese);

 

六.String转JSONArray

 

String jsonMessage = "[{'num':'成绩', '外语':88, '历史':65, '地理':99, 'object':{'aaa':'1111','bbb':'2222','cccc':'3333'}}," +           "{'num':'兴趣', '外语':28, '历史':45, '地理':19, 'object':{'aaa':'11a11','bbb':'2222','cccc':'3333'}}," +           "{'num':'爱好', '外语':48, '历史':62, '地理':39, 'object':{'aaa':'11c11','bbb':'2222','cccc':'3333'}}]";  

 

JSONArray myJsonArray = JSONArray.fromObject(jsonMessage);  

 

七.String转数组

 

String string = "a,b,c"; String [] stringArr= string.split(",");  //注意分隔符是需要转译

 

如果是"abc"这种字符串,就直接

 

String string = "abc" ; char [] stringArr = string.toCharArray(); //注意返回值是char数组 如果要返回byte数组就直接使用getBytes方法就ok了

 

String string = "abc" ; byte [] stringArr = string.getBytes();

 

八、数组转String

 

char[] data={a,b,c}; 

 

String s=new String(data); 

 

注:本文是通过自己的总结和总结他人经验得出来的结论,学疏才浅如果错误大家可以指出并改正。

 

 

Thread和Runnable简介

Runnable 是一个接口,该接口中只包含了一个run()方法

Thread 是一个类。Thread本身就实现了Runnable接口

Thread 和 Runnable 的相同点:都是“多线程的实现方式”。

Thread 和 Runnable 的不同点:

Thread 是类,而Runnable是接口;Thread本身是实现了Runnable接口的类。我们知道“一个类只能有一个父类,但是却能实现多个接口”,因此Runnable具有更好的扩展性。

此外,Runnable还可以用于“资源的共享”。即,多个线程都是基于某一个Runnable对象建立的,它们会共享Runnable对象上的资源。

通常,建议通过“Runnable”实现多线程!

 

start() 和 run()的区别说明

start() : 它的作用是启动一个新线程,新线程会执行相应的run()方法。start()不能被重复调用。

run()   : run()就和普通的成员方法一样,可以被重复调用。单独调用run()的话,会在当前线程中执行run(),而并不会启动新线程!

 

1. synchronized原理

在java中,每一个对象有且仅有一个同步锁。这也意味着,同步锁是依赖于对象而存在。

当我们调用某对象的synchronized方法时,就获取了该对象的同步锁。例如,synchronized(obj)就获取了“obj这个对象”的同步锁。

不同线程对同步锁的访问是互斥的。也就是说,某时间点,对象的同步锁只能被一个线程获取到!通过同步锁,我们就能在多线程中,实现对“对象/方法”的互斥访问。 例如,现在有两个线程A和线程B,它们都会访问“对象obj的同步锁”。假设,在某一时刻,线程A获取到“obj的同步锁”并在执行一些操作;而此时,线程B也企图获取“obj的同步锁” —— 线程B会获取失败,它必须等待,直到线程A释放了“该对象的同步锁”之后线程B才能获取到“obj的同步锁”从而才可以运行。

 

synchronized代码块可以更精确的控制冲突限制访问区域,有时候表现更高效率

 

2. synchronized基本规则

第一条: 当一个线程访问“某对象”的“synchronized方法”或者“synchronized代码块”时,其他线程对“该对象”的该“synchronized方法”或者“synchronized代码块”的访问将被阻塞。

第二条: 当一个线程访问“某对象”的“synchronized方法”或者“synchronized代码块”时,其他线程仍然可以访问“该对象”的非同步代码块。

第三条: 当一个线程访问“某对象”的“synchronized方法”或者“synchronized代码块”时,其他线程对“该对象”的其他的“synchronized方法”或者“synchronized代码块”的访问将被阻塞。

 

4. 实例锁 和 全局锁

实例锁 -- 锁在某一个实例对象上。如果该类是单例,那么该锁也具有全局锁的概念。

               实例锁对应的就是synchronized关键字。

全局锁 -- 该锁针对的是类,无论实例多少个对象,那么线程都共享该锁。

               全局锁对应的就是static synchronized(或者是锁在该类的class或者classloader对象上)。

   

Thread和Runnable的异同点

Thread 和 Runnable 的相同点:都是“多线程的实现方式”。

Thread 和 Runnable 的不同点:

Thread 是类,而Runnable是接口;Thread本身是实现了Runnable接口的类。我们知道“一个类只能有一个父类,但是却能实现多个接口”,因此Runnable具有更好的扩展性。

此外,Runnable还可以用于“资源的共享”。即,多个线程都是基于某一个Runnable对象建立的,它们会共享Runnable对象上的资源。

通常,建议通过“Runnable”实现多线程!

 

mythread.start()会启动一个新线程,并在新线程中运行run()方法。

而mythread.run()则会直接在当前线程中运行run()方法,并不会启动一个新线程来运行run()。

 

 

为什么notify(), wait()等函数定义在Object中,而不是Thread中

Object中的wait(), notify()等函数,和synchronized一样,会对“对象的同步锁”进行操作。

wait()会使“当前线程”等待,因为线程进入等待状态,所以线程应该释放它锁持有的“同步锁”,否则其它线程获取不到该“同步锁”而无法运行!

OK,线程调用wait()之后,会释放它锁持有的“同步锁”;而且,根据前面的介绍,我们知道:等待线程可以被notify()或notifyAll()唤醒。现在,请思考一个问题:notify()是依据什么唤醒等待线程的?或者说,wait()等待线程和notify()之间是通过什么关联起来的?答案是:依据“对象的同步锁”。

负责唤醒等待线程的那个线程(我们称为“唤醒线程”),它只有在获取“该对象的同步锁”(这里的同步锁必须和等待线程的同步锁是同一个),并且调用notify()或notifyAll()方法之后,才能唤醒等待线程。虽然,等待线程被唤醒;但是,它不能立刻执行,因为唤醒线程还持有“该对象的同步锁”。必须等到唤醒线程释放了“对象的同步锁”之后,等待线程才能获取到“对象的同步锁”进而继续运行。

总之,notify(), wait()依赖于“同步锁”,而“同步锁”是对象锁持有,并且每个对象有且仅有一个!这就是为什么notify(), wait()等函数定义在Object类,而不是Thread类中的原因。

 

yield() 与 wait()的比较

(01) wait()是让线程由“运行状态”进入到“等待(阻塞)状态”,而yield()是让线程由“运行状态”进入到“就绪状态”。

(02) wait()是会线程释放它所持有对象的同步锁,而yield()方法不会释放锁。

 

sleep() 与 wait()的比较

我们知道,wait()的作用是让当前线程由“运行状态”进入“等待(阻塞)状态”的同时,也会释放同步锁。而sleep()的作用是也是让当前线程由“运行状态”进入到“休眠(阻塞)状态”。

但是,wait()会释放对象的同步锁,而sleep()则不会释放锁。

 

join() 的作用:让“主线程”等待“子线程”结束之后才能继续运行。

 

 

interrupted() 和 isInterrupted()的区别

最后谈谈 interrupted() 和 isInterrupted()。

interrupted() 和 isInterrupted()都能够用于检测对象的“中断标记”。

区别是,interrupted()除了返回中断标记之外,它还会清除中断标记(即将中断标记设为false);而isInterrupted()仅仅返回中断标记。

 

线程优先级的介绍

java 中的线程优先级的范围是1~10,默认的优先级是5。“高优先级线程”会优先于“低优先级线程”执行。

java 中有两种线程:用户线程和守护线程。可以通过isDaemon()方法来区别它们:如果返回false,则说明该线程是“用户线程”;否则就是“守护线程”。

用户线程一般用户执行用户级任务,而守护线程也就是“后台线程”,一般用来执行后台任务。需要注意的是:Java虚拟机在“用户线程”都结束后会后退出。

 

并发领域有2个问题,互斥和同步。

互斥:同一时刻,只允许一个线程访问共享资源。

同步:线程之间的协作和通信。

 

java的并发包通过Lock和Condition这两个接口来分别处理互斥和同步。

 

1 Lock

1.1 和 synchronized 的对比

Lock是为了处理互斥问题而存在的,而我们前面提到的synchronized也是处理互斥问题。但是这两个其实有一些区别的:

jdk1.6之前,synchronized是重量锁,效率比Lock低,但是随着JVM对synchronized的不断优化,性能已经差别不那么明显了。

Lock需要显示用代码加锁和解锁,synchronized是自动的。

synchronized在拿不到锁的情况下,会调用无参的wait()让线程一直挂起;而Lock可以设置一定时间后放弃,这样可以防止死锁发生,因为破坏了 “占有且等待”条件,主动释放了资源。

Lock支持响应中断,也就是在一个线程获取到锁还没有释放的时候,其他线程可以中断这个线程使其释放锁。synchronized不支持。

Lock支持尝试获取锁,失败就返回false了,而不进入阻塞状态。

最后3点对应了Lock的三个方法:

boolean tryLock(long time, TimeUnit unit) throws InterruptedException;

void lockInterruptibly() throws InterruptedException;

boolean tryLock();

 

ReadWriteLock 读写锁

读写锁并不是java的概念,是一个通用技术,所有的读写锁都遵从3大原则:

1 允许多个线程同时读变量。

2 只允许一个线程写变量

3 如果一个线程正在写共享变量,禁止其他线程读这个共享变量。

 

在一个class中定义的字段,我们称之为实例字段。实例字段的特点是,每个实例都有独立的字段,各个实例的同名字段互不影响。

 

还有一种字段,是用static修饰的字段,称为静态字段:static field。

 

实例字段在每个实例中都有自己的一个独立“空间”,但是静态字段只有一个共享“空间”,所有实例都会共享该字段

 

enum

为了让编译器能自动检查某个值在枚举的集合内,并且,不同用途的枚举需要不同的类型来标记,不能混用,我们可以使用enum来定义枚举类

 

所以对于写多读少的操作,使用悲观锁,对于读多写少的操作,可以使用乐观锁。

 

Runtime:运行时,是一个封装了JVM的类。每一个JAVA程序实际上都是启动了一个JVM进程,每一个JVM进程都对应一个Runtime实例,此实例是由JVM为其实例化的。所以我们不能实例化一个Runtime对象,应用程序也不能创建自己的 Runtime 类实例,但可以通过 getRuntime 方法获取当前Runtime运行时对象的引用。一旦得到了一个当前的Runtime对象的引用,就可以调用Runtime对象的方法去控制Java虚拟机的状态和行为。

查看官方文档可以看到,Runtime类中没有构造方法,本类的构造方法被私有化了, 所以才会有getRuntime方法返回本来的实例化对象,这与单例设计模式不谋而合

public static Runtime getRuntime()

Runtime类本身就是单例设计模式的一种应用,因为整个JVM中只存在一个Runtime类的对象,可以使用Runtime类取得JVM的系统信息,或者使用gc()方法释放掉垃圾空间,还可以运行本机的程序

 

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics