StringBuffer类

方法:

String 

增加
    append(boolean b)    可以添加任意类型 的数据到容器中
    insert(int offset, boolean b)  指定插入的索引值,插入对应 的内容。 

删除
    delete(int start, int end)  根据指定的开始与结束的索引值删除对应的内容。
    deleteCharAt(int index)   根据指定 的索引值删除一个字符。


修改

    replace(int start, int end, String str) 根据指定 的开始与结束索引值替代成指定的内容。
    reverse()   翻转字符串缓冲类的内容。  abc--->cba

    setCharAt(int index, char ch)  把指定索引值的字符替换指定的字符。 
    substring(int start, int end)  根据指定的索引值截取子串。
    ensureCapacity(int minimumCapacity)  指定StringBuffer内部的字符数组长度的。

查看
    indexOf(String str, int fromIndex) 查找指定的字符串第一次出现的索引值,并且指定开始查找的位置。
    lastIndexOf(String str) 

    capacity() 查看当前字符数组的长度。 
    length() 

    charAt(int index) 
    toString()   把字符串缓冲类的内容转成字符串返回。

StringBuffer 与 StringBuilder的相同处与不同处:

相同点:
    1. 两个类都是字符串缓冲类。
    2. 两个类的方法都是一致的。
不同点:
    1. StringBuffer是线程安全的,操作效率低 ,StringBuilder是线程非安全的,操作效率高。
    2. StringBuffer是jdk1.0出现 的,StringBuilder 是jdk1.5的时候出现的。

推荐使用: StringBuilder,因为操作效率高。

System类

System 系统类 主要用于获取系统的属性数据。

System类常用的方法:

arraycopy(Object src, int srcPos, Object dest, int destPos, int length) 一般
    src - 源数组。
    srcPos - 源数组中的起始位置。
    dest - 目标数组。
    destPos - 目标数据中的起始位置。
    length - 要复制的数组元素的数量。

currentTimeMillis()  获取当前系统时间,返回毫秒值(1970-1-1到今天的毫秒值)。       重点
exit(int status)  退出jvm  如果参数是0表示正常退出jvm,非0表示异常退出jvm。    一般
/应用

try{
exit(0)//如果在try里面,则传0
}catch(){
exit(1)//如果系统异常需要退出,我们一般传非0
}


gc()    建议jvm赶快启动垃圾回收期回收垃圾,不一定马上启动。
getenv(String name) 根据环境变量的名字获取环境变量。
getProperty(key) 
finalize()  如果一个对象被垃圾回收器回收的时候(此对象没有被引用的时候),会先调用对象的finalize()方法。

//
class Person{

String name;

public Person(String name) {
    this.name = name;
}

@Override
public void finalize() throws Throwable {
    super.finalize();
    System.out.println(this.name+"被回收了..");
}
}

public class Demo1 {

public static void main(String[] args) {

    int[] srcArr = {10,12,14,16,19};
    //把srcArr的数组元素拷贝 到destArr数组中。
    int[] destArr = new int[4];

    System.arraycopy(srcArr, 1, destArr, 0,4);
    //System.exit(0); //jvm退出..  注意: 0或者非0的 数据都可以退出jvm。对于用户而言没有任何区别,对操作系统有影响
    System.out.println("目标数组的元素:"+ Arrays.toString(destArr)); // 0 14 16 0
    System.out.println("当前的系统时间:" + System.currentTimeMillis());
    System.out.println("环境变量:"+System.getenv("JAVA_HOME"));


    for(int i = 0 ; i<4; i++){
        new Person("狗娃"+i);
        System.gc(); //建议马上启动垃圾回收期
    }

    Properties properties = System.getProperties();  //获取系统的所有属性。
    properties.list(System.out);
    String value = System.getProperty("os.name");//根据系统的属性名获取对应的属性值
    System.out.println("当前系统:"+value);
}

}

RunTime类

该类类主要代表了应用程序运行的环境。

getRuntime()  返回当前应用程序的运行环境对象。
exec(String command)  根据指定的路径执行对应的可执行文件。
freeMemory()   返回 Java 虚拟机中的空闲内存量。。 以字节为单位
maxMemory()    返回 Java 虚拟机试图使用的最大内存量。
totalMemory()    返回 Java 虚拟机中的内存总量


public static void main(String[] args) throws IOException, InterruptedException {
    Runtime runtime = Runtime.getRuntime();
//      Process process = runtime.exec("C:\\Windows\\notepad.exe");
//      Thread.sleep(3000); //让当前程序停止3秒。
//      process.destroy();
    System.out.println(" Java虚拟机中的空闲内存量。"+runtime.freeMemory());
    System.out.println("Java 虚拟机试图使用的最大内存量:"+ runtime.maxMemory());
    System.out.println("返回 Java 虚拟机中的内存总量:"+ runtime.totalMemory());
}

日期类

Date、Calendar、SimpleDateFormat

Calendar.HOUR_OF_DAY 24小时制

Calendar.HOUR 12小时制

public static void main(String[] args) throws ParseException {
    /*Date date = new Date(); // 获取当前的系统时间
    System.out.println("年份:"+ date.getYear());*/
    /*
    Calendar calendar = Calendar.getInstance(); //获取当前的系统时间。
    System.out.println("年:"+ calendar.get(Calendar.YEAR));
    System.out.println("月:"+ (calendar.get(Calendar.MONTH)+1));
    System.out.println("日:"+ calendar.get(Calendar.DATE));

    System.out.println("时:"+ calendar.get(Calendar.HOUR_OF_DAY));
    System.out.println("分:"+ calendar.get(Calendar.MINUTE));
    System.out.println("秒:"+ calendar.get(Calendar.SECOND));

    // 显示 当前系统时间: 2014年12月26日  xx时xx分xx秒   

     *  日期格式化类    SimpleDateFormat 
     *          作用1: 可以把日期转换转指定格式的字符串     format()
     *          作用2: 可以把一个 字符转换成对应的日期。    parse()   生日
     *      
     */
    Date date = new Date(); //获取当前的系统时间。
    SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy年MM月dd日   HH:mm:ss") ; //指定格式创建了一个日期格式化对象。
    String time = dateFormat.format(date);  //可以把日期转换转指定格式的字符串
    System.out.println("当前的系统时间:"+ time);

    String birthday = "2000年12月26日   11:29:08";
    Date date2 = dateFormat.parse(birthday);  //注意: 指定的字符串格式必须要与SimpleDateFormat的模式要一致。
    System.out.println(date2);

    Date date21 =new Date();
    SimpleDateFormat dateFormat2 = new SimpleDateFormat("yyyy年MM月dd日  HH:mm:ss");
    String time2 =dateFormat.format(date21);
    String time21=dateFormat.format(date);
    System.out.println("当前的系统时间:"+time);
    String birthday1= "2000年12月26日  11:28:08";
    Date date22=dateFormat.parse(birthday1);
    System.out.println(date22);
}

Math 数学类

abs(double a)  获取绝对值
ceil(double a)  向上取整
floor(double a)  向下取整
round(float a)   四舍五入
random()   产生一个随机数. 大于等于 0.0 且小于 1.0 的伪随机 double 值
编写一个函数随机产生四位的验证码。
public static void main(String[] args) {
    /*
    Random random = new Random();
    int randomNum = random.nextInt(11); //产生 的 随机数就是0-10之间
    System.out.println("随机数:"+ randomNum);
    */
    char[] arr = {'中','国','传','a','Q','f','B'};
    StringBuilder sb = new StringBuilder();
    Random random = new Random();
    //需要四个随机数,通过随机数获取字符数组中的字符,
    for(int i  = 0 ; i< 4 ; i++){
        int index = random.nextInt(arr.length);  //产生的 随机数必须是数组的索引值范围之内的。
        sb.append(arr[index]);
    }
    System.out.println("验证码:"+ sb);
}

线程

进程

进程 : 正在执行的程序称作为一个进程。 进程负责了内存空间的划分。

问题: windows号称是多任务的操作系统,那么windows是同时运行多个应用程序吗?

从宏观的角度: windows确实是在同时运行多个应用程序。

从微观角度: cpu是做了一个快速切换执行的动作,由于速度态度,所以我感觉不到在切换而已。

单核的cpu在一个时间片中只能执行一个程序

线程

线程: 线程在一个进程 中负责了代码的执行,就是进程中一个执行路径,

多线程: 在一个进程中有多个线程同时在执行不同的任务。

运行任何一个java程序,jvm在运行的时候都会创建一个main线程执行main方法中所有代码。

一个java应用程序至少有几个线程?

至少有两个线程, 一个是主线程负责main方法代码的执行,一个是垃圾回收器线程,负责了回收垃圾。

多线程的好处:

1. 解决了一个进程能同时执行多个任务的问题。
2. 提高了资源的利用率。

多线程 的弊端:

1. 增加cpu的负担。
2. 降低了一个进程中线程的执行概率。
3. 引发了线程安全 问题。
4. 出现了死锁现象。
如何创建多线程:
创建线程的方式:

    方式一:
        1. 自定义一个类继承Thread类。
        2. 重写Thread类的run方法 , 把自定义线程的任务代码写在run方法中
            疑问: 重写run方法的目的是什么?  
           每个线程都有自己的任务代码,jvm创建的主线程的任务代码就是main方法中的所有代码, 自定义线程的任务代码就写在run方法中,自定义线程负责了run方法中代码。    
        3. 创建Thread的子类对象,并且调用start方法开启线程。

        注意: 一个线程一旦开启,那么线程就会执行run方法中的代码,run方法千万不能直接调用,直接调用run方法就相当调用了一个普通的方法而已
            并没有开启新的线程。


public class Demo1 extends Thread {

@Override  //把自定义线程的任务代码写在run方法中。
public void run() {
    for(int i  = 0 ; i < 100 ; i++){
        System.out.println("自定义线程:"+i);
    }
}


public static void main(String[] args) {
    //创建了自定义的线程对象。
    Demo1 d = new Demo1();
    //调用start方法启动线程
    d.start();

    for(int i  = 0 ; i < 100 ; i++){
        System.out.println("main线程:"+i);
    }
}   
}
重新快捷方式:鼠标右键—source—Override/implement methods
模拟QQ视频与聊天同时在执行。

class TalkThread extends Thread{

@Override
public void run() {
    while(true){
        System.out.println("hi,你好!开视频呗...");
    }
}
}


class VideoThread extends Thread{

@Override
public void run() {
    while(true){
        System.out.println("视频视频....");
    }
}
}

public class Demo2 {

public static void main(String[] args) {
    TalkThread talkThread = new TalkThread();
    talkThread.start();
    VideoThread videoThread = new VideoThread();
    videoThread.start();
}
}

线程生命周期

线程的生命周期图

线程常用的方法:
 Thread(String name)     初始化线程的名字
 setName(String name)    设置线程对象名
 getName()             返回线程的名字


 sleep()                 线程睡眠指定的毫秒数。 静态的方法,哪个线程执行了sleep方法代码那么就是哪个线程睡眠。(执行者在睡眠)

 currentThread()      返回当前的线程对象,该方法是一个静态的方法, 注意: 那个线程执行了currentThread()代码就返回那个线程 的对象。

 getPriority()             返回当前线程对象的优先级   默认线程的优先级是5,数字越大优先级越高
 setPriority(int newPriority) 设置线程的优先级    虽然设置了线程的优先级,但是具体的实现取决于底层的操作系统的实现(最大的优先级是10 ,最小的1 , 默认是5)。

public class Demo3 extends Thread {

public Demo3(String name){
    super(name); //调用了Thread类的一个 参数的构造方法。
}


@Override
public void run() {
    /*System.out.println("this:"+ this);
    System.out.println("当前线程对象:" + Thread.currentThread()); */

    for (int i = 0; i < 100 ; i++) {
        System.out.println(Thread.currentThread().getName()+":"+i);


        /*try {
            Thread.sleep(100);  //为什么在这里不能抛出异常,只能捕获?? Thread类的run方法没有抛出异常类型,所以子类不能抛出异常类型。
        } catch (InterruptedException e) {
            e.printStackTrace();
        } */
    }


}


public static void main(String[] args) throws InterruptedException {
    //创建了一个线程对象
    Demo3 d = new Demo3("狗娃");
    d.setPriority(10); //设置线程 的优先级。 优先级的数字越大,优先级越高  , 优先级的范围是1~10
    d.start();

    for (int i = 0; i < 100 ; i++) {
        System.out.println(Thread.currentThread().getName()+":"+i);
    }

    /*
    System.out.println("自定义线程的优先级:"+d.getPriority());  //线程的优先级默认是5
    System.out.println("主线程的优先级:"+Thread.currentThread().getPriority());


    d.start();

    d.setName("铁蛋"); //setName设置线程的名字
    d.start(); //开启线程 

    Thread mainThread = Thread.currentThread();
    System.out.println("主线程的名字:"+ mainThread.getName());
*/
}

}

模拟3个窗口同时在售50张票

问题1 :为什么50张票被卖出了150次?

出现 的原因: 因为num是非静态的,非静态的成员变量数据是在每个对象中都会维护一份数据的,三个线程对象就会有三份。

解决方案:把num票数共享出来给三个线程对象使用。使用static修饰。

问题2: 出现了线程安全问题 ?

出现线程安全问题的根本原因:

1. 存在两个或者两个以上 的线程对象,而且线程之间共享着一个资源。
2. 有多个语句操作了共享资源。

线程 安全问题的解决方案:sun提供了线程同步机制让我们解决这类问题的。

java线程同步机制的方式:

    方式一:同步代码块

        同步代码块的格式:

            synchronized(锁对象){
                需要被同步的代码...
            }

同步代码块要注意事项:

    1. 任意的一个对象都可以做为锁对象。
    2. 在同步代码块中调用了sleep方法并不是释放锁对象的。
    3. 只有真正存在线程安全问题的时候才使用同步代码块,否则会降低效率的。
    4. 多线程操作的锁 对象必须 是唯一共享 的。否则无效。

需求: 一个银行账户5000块,两夫妻一个拿着 存折,一个拿着卡,开始取钱比赛,每次只能取一千块,要求不准出现线程安全问题。

方式二:同步函数


class SaleTicket extends Thread{


 static int num = 50;//票数  非静态的成员变量,非静态的成员变量数据是在每个对象中都会维护一份数据的。

 static Object o = new Object();

 public SaleTicket(String name) {
    super(name);
}

@Override
public void run() {
    while(true){
        //同步代码块
        synchronized ("锁") {                
            if(num>0){
                System.out.println(Thread.currentThread().getName()+"售出了第"+num+"号票");
                try {
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                num--;
            }else{
                System.out.println("售罄了..");
                break;
            }
        }

    }
}   
} 


public class Demo4 {

public static void main(String[] args) {
    //创建三个线程对象,模拟三个窗口
    SaleTicket thread1 = new SaleTicket("窗口1");
    SaleTicket thread2 = new SaleTicket("窗口2");
    SaleTicket thread3 = new SaleTicket("窗口3");
    //开启线程售票
    thread1.start();
    thread2.start();
    thread3.start();
}
}
posted on 2018-04-02 22:20  NE_STOP  阅读(1)  评论(0编辑  收藏  举报  来源