StringBuffer

增加

    append(boolean b)    可以添加任意类型的数据到容器中

    insert(int offset,boolean b)  指定插入的索引值,插入对应的内容    (offset可以理解为想插入的东西在插入后的索引值为多少,也就是想插入地方右区间的索引值)

删除

    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)   查找指定字符串第一次出现的索引值,并且指定开始查找的位置

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

    charAt(int index)   根据指定的索引值查找字符

    lastIndexOf(String str)  查找指定字符最后一次出现的索引值

    length() 存储的字符个数

    toString()   把字符串缓冲类的内容转换成字符串返回

判断

public static void main(String[] args) {// TODO Auto-generated method stub//先使用StringBuffer无参的构造函数创建一个字符串缓冲类。StringBuffer sb=new StringBuffer();sb.append("abc");System.out.println("字符串缓冲类的内容:"+sb);/* 添加sb.append(true);sb.append(3.14f);System.out.println("字符串缓冲类的内容:"+sb);*///插入sb.insert(2, "小明");System.out.println("字符串缓冲类的内容:"+sb);//删除sb.delete(2, 4);   //删除的时候也是包头不包尾的System.out.println("字符串缓冲类的内容:"+sb);sb.insert(2, "小明");sb.deleteCharAt(3);System.out.println("字符串缓冲类的内容:"+sb);}结果:
字符串缓冲类的内容:abc
字符串缓冲类的内容:ab小明c
字符串缓冲类的内容:abc
字符串缓冲类的内容:ab小c

public static void main(String[] args) {// TODO Auto-generated method stub//先使用StringBuffer无参的构造函数创建一个字符串缓冲类。StringBuffer sb=new StringBuffer();sb.append("abc");System.out.println("字符串缓冲类的内容:"+sb);/* 添加sb.append(true);sb.append(3.14f);System.out.println("字符串缓冲类的内容:"+sb);*///插入sb.insert(2, "小明");System.out.println("字符串缓冲类的内容:"+sb);//删除/*sb.delete(2, 4);   //删除的时候也是包头不包尾的System.out.println("字符串缓冲类的内容:"+sb);sb.insert(2, "小明");sb.deleteCharAt(3);System.out.println("字符串缓冲类的内容:"+sb);*///修改sb.replace(2, 4, "陈小狗");System.out.println("字符串缓冲类的内容:"+sb);sb.reverse();System.out.println("字符串缓冲类的内容:"+sb);sb.reverse();sb.setCharAt(3, '红');System.out.println("字符串缓冲类的内容:"+sb);System.out.println("字符串的内容:"+sb.substring(2, 4));sb.ensureCapacity(20);}结果:
字符串缓冲类的内容:abc
字符串缓冲类的内容:ab小明c
字符串缓冲类的内容:ab陈小狗c
字符串缓冲类的内容:c狗小陈ba
字符串缓冲类的内容:ab陈红狗c
字符串的内容:陈红

public static void main(String[] args) {// TODO Auto-generated method stubStringBuffer sb=new StringBuffer();sb.append("abcjavaabc");//查找System.out.println("索引值为:"+sb.indexOf("abc", 0));System.out.println("索引值为:"+sb.indexOf("abc", 3));//sb.ensureCapacity(20);sb.append("javajava");System.out.println("查看字符数组的长度:"+sb.capacity());System.out.println("存储字符的个数:"+sb.length());System.out.println("根据指定的索引值查找字符:"+sb.charAt(2));System.out.println("转换成字符串输出:"+sb.toString());}结果:
索引值为:0
索引值为:7
查看字符数组的长度:34
存储字符的个数:18
根据指定的索引值查找字符:c
转换成字符串输出:abcjavaabcjavajava

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

    相同点:

      1.两个类都是字符串缓冲类

      2.两个类的方法与实现都是一致的

    不同点:

      1.StringBuffer是线程安全的,操作效率低,StringBuilder是线程非安全的,操作效率高

      2.StringBuffer是jdk1.0出现的,StringBuilder是jdk1.5的时候出现的

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

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

System类常用的方法:

    arraycopy(Object src, int srcPos, Object dest, int destPos, int length)

import java.util.*;
public class Demo1 {
/*arraycopy(Object src, int srcPos, Object dest, int destPos, int length)  src - 源数组。srcPos - 源数组中的起始位置。dest - 目标数组。destPos - 目标数据中的起始位置。length - 要复制的数组元素的数量。* */public static void main(String[] args) {// TODO Auto-generated method stubint[] srcArr= {10,12,14,16,19};//把srcArr数组的元素拷贝到destArr数组中int[] destArr=new int[4];System.arraycopy(srcArr, 1, destArr, 0, 4);System.out.println("目标数组的元素:"+Arrays.toString(destArr));}}结果:
目标数组的元素:[12, 14, 16, 19]

    currentTimeMillis()    获取当前系统时间       重点

System.out.println("当前的系统时间是:"+System.currentTimeMillis());结果:
当前的系统时间是:1549623586306

    exit(int status)      退出jvm    如果参数是0表示正常退出jvm,非0表示异常退出jvm  0或者非0的数据都可以退出jvm,对于用户而言没有任何区别    一般

public static void main(String[] args) {// TODO Auto-generated method stubint[] 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));System.out.println("当前的系统时间是:"+System.currentTimeMillis());}结果:

(编程习惯:try块中一般传0,catch中一般传非0,其实传什么也可以达到效果)?

    gc()       建议jvm赶快启动垃圾回收器回收垃圾

finalize() 如果一个对象被回收器回收的时候,会先调用对象的finalize()方法    我们如果想要看到System.gc()的结果,可以重写finalize方法

import java.util.*;
public class Demo1 {
/*
gc()            建议jvm赶快启动垃圾回收器回收垃圾
finalize()         如果一个对象被回收器回收的时候,会先调用对象的finalize()方法* */public static void main(String[] args) {// TODO Auto-generated method stubint[] 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));System.out.println("当前的系统时间是:"+System.currentTimeMillis());for (int i=0;i<4;i++) {new Person("狗娃"+i);System.gc();  //建议赶快启动垃圾回收器回收
        }}}
class Person{String name;public Person(String name) {this.name=name;}@Overrideprotected void finalize() throws Throwable {// TODO Auto-generated method stubsuper.finalize();System.out.println(this.name+"被回收了");}
}结果:
目标数组的元素:[12, 14, 16, 19]
当前的系统时间是:1549627330079
狗娃0被回收了
狗娃2被回收了
狗娃3被回收了
狗娃1被回收了

    getenv(String name)   根据环境变量的名字获取环境变量

System.out.println("环境变量:"+System.getenv("JAVA_HOME"));结果:
环境变量:D:\JAVA\jdk\

    getProperties()      获取当前的系统所有的属性

    getProperty(String key)   根据系统的属性名获取对应的属性值(获取一个属性)

//Properties properties=System.getProperties();//properties.list(System.out);String value=System.getProperty("os.name");System.out.println("当前系统:"+value);结果:
当前系统:Windows 10

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

    getRuntime()         返回当前应用程序的运行环境对象
    exec(String command)      根据指定的路径执行对应的可执行文件

import java.io.IOException;/*getRuntime()   返回当前应用程序的运行环境对象exec(String command)     根据指定的路径执行对应的可执行文件*/
public class Demo2 {public static void main(String[] args) throws IOException, InterruptedException {// TODO Auto-generated method stubRuntime runtime=Runtime.getRuntime();Process process=runtime.exec("C:\\Windows\\notepad.exe");Thread.sleep(3000); //让当前程序停止3秒
        process.destroy();}}结果:
打开记事本,三秒之后关闭

      freeMemory()       返回jvm空闲的内存,以字节为单位。
      maxMemory()        返回 Java 虚拟机试图使用的最大内存量
      totalMemory()        返回 Java 虚拟机中的内存总量

public static void main(String[] args) throws IOException, InterruptedException {// TODO Auto-generated method stubRuntime runtime=Runtime.getRuntime();System.out.println("jvm空闲的内存量:"+runtime.freeMemory());System.out.println("Java 虚拟机试图使用的最大内存量"+runtime.maxMemory());System.out.println("Java 虚拟机的内存总量"+runtime.totalMemory());}结果:
jvm空闲的内存量:124484880
Java 虚拟机试图使用的最大内存量2000683008
Java 虚拟机的内存总量125829120

日期类Date

使用Calendar.getInstance()获取Calendar对象

import java.util.Calendar;
import java.util.Date;
public class Demo3 {public static void main(String[] args) {// TODO Auto-generated method stub//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));}}结果:
年:2019
月:2
日:12
时:9
分:11
秒:20

日期格式化类SimpleDateFormat

作用:

  1. 可以把日期转换成指定格式的字符串  format()
  2. 可以把一个字符串转换成对应的日期       parse()
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
public class Demo3 {public static void main(String[] args) throws ParseException {// TODO Auto-generated method stub//Date date=new Date();   //获取当前的系统时间//System.out.println("年份:"+date.getYear());//显示当前的系统时间:2019年2月12日 xx时xx分xx秒/*日期格式化类SimpleDateFormat*     作用1:可以把日期转换成指定格式的字符串        format()*     作用2:可以把一个字符串转换成对应的日期        parse()* */Date date=new Date();SimpleDateFormat dateFormat=new SimpleDateFormat(); //使用了默认的格式创建了一个日期格式化对象String time=dateFormat.format(date);System.out.println("当前的系统时间:"+time);SimpleDateFormat dateFormat2=new SimpleDateFormat("yyyy年MM月dd日  HH:mm:ss");time=dateFormat2.format(date);System.out.println("当前的系统时间:"+time);String birthday="1999年11月1日  19:27:35";Date date2=dateFormat2.parse(birthday); //注意:指定的字符串格式必须要与SimpleDateFormat的模式要一致,空格个数也要考虑
        System.out.println(date2);}}结果:
当前的系统时间:2019/2/12 上午10:55
当前的系统时间:2019年02月12日  10:55:31
Mon Nov 01 19:27:35 CST 1999

Math类(数学类)    主要是提供了很多的数学公式

abs(double a)          获取绝对值
ceil(double a)        向上取整
floor(double a)         向下取整
round(float a)        四舍五入
random()          产生一个随机数,返回带正号的 double 值,该值大于等于 0.0 且小于 1.0

public static void main(String[] args) {// TODO Auto-generated method stubSystem.out.println("绝对值:"+Math.abs(-3));System.out.println("向上取整:"+Math.ceil(3.14));System.out.println("向上取整:"+Math.ceil(-3.14));System.out.println("向下取整:"+Math.floor(3.14));System.out.println("向下取整:"+Math.floor(-3.14));System.out.println("四舍五入:"+Math.round(3.54));System.out.println("四舍五入:"+Math.round(3.49));System.out.println("随机数:"+Math.random());}结果:
绝对值:3
向上取整:4.0
向上取整:-3.0
向下取整:3.0
向下取整:-4.0
四舍五入:4
四舍五入:3
随机数:0.6458472762144221

随机数类:(Random类)

import java.util.Random;/*Random类        随机数类*/
public class Demo5 {public static void main(String[] args) {// TODO Auto-generated method stubRandom random=new Random();int randomNum=random.nextInt(10)+1;//产生的随机数是1-10之间的System.out.println("随机数:"+randomNum);}}结果:
随机数:2

注意:随机数产生的区间是根据所给区间   左闭右开   的,也就是包含左边的临界值,不包含右边的

需求:编写一个函数随机产生四位的验证码。

import java.util.Random;/*Random类        随机数类*/
public class Demo5 {public static void main(String[] args) {// TODO Auto-generated method stub/*Random random=new Random();int randomNum=random.nextInt(10)+1;//产生的随机数是1-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]);}//String str=sb.toString();//System.out.println("验证码为:"+str);System.out.println("验证码为:"+sb);}}结果:
验证码为:QB传B

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

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

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

    从微观的角度: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 Demo6 extends Thread{@Override        //把自定义线程的任务写在run方法中public void run() {// TODO Auto-generated method stubfor (int i=0;i<10;i++) {System.out.println("自定义线程:"+i);}super.run();}public static void main(String[] args) {// TODO Auto-generated method stub//创建了自定义的线程对象Demo6 d=new Demo6();//调用start方法启动线程
        d.start();for (int i=0;i<10;i++) {System.out.println("main线程:"+i);}}}结果:
main线程:0
自定义线程:0
main线程:1
自定义线程:1
main线程:2
自定义线程:2
自定义线程:3
自定义线程:4
main线程:3
main线程:4
main线程:5
main线程:6
main线程:7
main线程:8
main线程:9
自定义线程:5
自定义线程:6
自定义线程:7
自定义线程:8
自定义线程:9

需求:模拟QQ视频与聊天同时进行

public class Demo7 {public static void main(String[] args) {// TODO Auto-generated method stubTalkThread talkThread=new TalkThread();talkThread.start();VideoThraead videoThread=new VideoThraead();videoThread.start();}}
class VideoThraead extends Thread{@Overridepublic void run() {// TODO Auto-generated method stubint i=0;while (i++<50) {System.out.println("视频");}super.run();}
}
class TalkThread extends Thread{@Overridepublic void run() {// TODO Auto-generated method stubint i=0;while (i++<50) {System.out.println("聊天");}super.run();}
}结果:
聊天
聊天
聊天
聊天
聊天
聊天
聊天
聊天
聊天
聊天
聊天
聊天
聊天
视频
视频
视频
视频
视频
视频
视频
视频
视频
视频
视频
视频
视频
视频
视频
视频
视频
视频
视频
视频
视频
视频
视频
视频
视频
视频
视频
视频
视频
视频
视频
视频
视频
视频
视频
视频
视频
视频
视频
视频
视频
视频
视频
视频
视频
视频
视频
视频
视频
视频
聊天
聊天
聊天
聊天
聊天
聊天
聊天
聊天
聊天
聊天
聊天
聊天
聊天
聊天
聊天
聊天
聊天
聊天
聊天
聊天
聊天
聊天
聊天
聊天
聊天
聊天
聊天
聊天
聊天
聊天
聊天
聊天
聊天
聊天
聊天
聊天
聊天

线程的生命周期图

线程常用的方法:

Thread(String name)     初始化线程的名字

getName()             返回线程的名字

setName(String name)    设置线程对象名

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

getPriority()             返回当前线程对象的优先级   默认线程的优先级是5,优先级的数字越大,优先级越高,优先级的范围是1~10,注意:线程的优先级高,并不意味着就一定先执行,只是抢到cpu的概率更大了

setPriority(int newPriority) 设置线程的优先级    虽然设置了线程的优先级,但是具体的实现取决于底层的操作系统的实现(最大的优先级是10 ,最小的1 , 默认是5)。

currentThread()      返回CPU正在执行的线程的对象     该方法是一个静态的方法,哪个线程执行了currentThread()代码就返回哪个线程的对象

public class Demo8 extends Thread{public Demo8() {}public Demo8(String name) {super(name);        //调用了Thread类的一个参数的构造方法
    }@Overridepublic void run() {// TODO Auto-generated method stubfor (int i=0;i<10;i++) {System.out.println(this.getName()+i);try {Thread.sleep(100);//这里只能捕获,不能抛出,因为其父类Thread的run方法并没有抛出异常,子类重写时抛出的异常类型要小于或等于父类抛出的异常} catch (InterruptedException e) {// TODO Auto-generated catch block
                    e.printStackTrace();}}super.run();}public static void main(String[] args) throws InterruptedException {// TODO Auto-generated method stub//创建了一个线程对象Demo8 d=new Demo8("狗娃");d.sleep(1000);d.setName("铁蛋");//d.setName("铁蛋");//设置线程的名字System.out.println("线程的名字:"+d.getName());d.start();}}结果:
线程的名字:铁蛋
铁蛋0
铁蛋1
铁蛋2
铁蛋3
铁蛋4
铁蛋5
铁蛋6
铁蛋7
铁蛋8
铁蛋9    先出来第一二行,然后每隔0.1秒出来一行

public class Demo8 extends Thread{public Demo8() {}public Demo8(String name) {super(name);        //调用了Thread类的一个参数的构造方法
    }@Overridepublic void run() {// TODO Auto-generated method stubSystem.out.println("this:"+this);System.out.println("当前线程对象:"+Thread.currentThread());for (int i=0;i<10;i++) {System.out.println(this.getName()+i);System.out.println(Thread.currentThread().getName()+i);/*try {Thread.sleep(100);//这里只能捕获,不能抛出,因为其父类Thread的run方法并没有抛出异常,子类重写时抛出的异常类型要小于或等于父类抛出的异常} catch (InterruptedException e) {// TODO Auto-generated catch blocke.printStackTrace();}*/}}public static void main(String[] args) throws InterruptedException {// TODO Auto-generated method stub//创建了一个线程对象Demo8 d=new Demo8("狗娃");System.out.println("自定义线程的优先级:"+d.getPriority());System.out.println("主线程的优先级:"+Thread.currentThread().getPriority());//d.sleep(1000);d.setName("铁蛋");//d.setName("铁蛋");//设置线程的名字System.out.println("线程的名字:"+d.getName());d.setPriority(10);d.start();for (int i=0;i<10;i++) {System.out.println(Thread.currentThread().getName()+i);}Thread mainThread=Thread.currentThread();System.out.println("主线程的名字:"+mainThread.getName());}}结果:
自定义线程的优先级:5
主线程的优先级:5
线程的名字:铁蛋
main0
main1
main2
main3
main4
this:Thread[铁蛋,10,main]
当前线程对象:Thread[铁蛋,10,main]
铁蛋0
铁蛋0
铁蛋1
铁蛋1
铁蛋2
铁蛋2
铁蛋3
铁蛋3
铁蛋4
铁蛋4
铁蛋5
铁蛋5
铁蛋6
铁蛋6
铁蛋7
铁蛋7
铁蛋8
铁蛋8
铁蛋9
铁蛋9
main5
main6
main7
main8
main9
主线程的名字:main

需求:模拟三个窗口在售50张票

public class Demo9 {public static void main(String[] args) {// TODO Auto-generated method stub//创建三个线程对象,模拟三个窗口SaleTicket thread1=new SaleTicket("窗口1");SaleTicket thread2=new SaleTicket("窗口2");SaleTicket thread3=new SaleTicket("窗口3");//开启线程售票
        thread1.start();thread2.start();thread3.start();}}
class SaleTicket extends Thread{static int num=50;//票数        不加static的时候是非静态的成员变量,非静态的成员变量数据是在每个对象中都会维护一份数据的。所以会出现三个窗口卖了150张票的情况public SaleTicket() {}public SaleTicket(String name) {// TODO Auto-generated constructor stubsuper(name);}@Overridepublic void run() {// TODO Auto-generated method stubwhile (true) {if (num>0) {System.out.println(Thread.currentThread().getName()+"售出了第"+num+"号票");num--;}else {System.out.println("售罄了...");break;}}//super.run();
    }
}

问题1:50张票售了150次

可以向票数上加static使其成为静态成员变量来解决

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

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

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

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

Java线程同步机制的方式:

    方式一:同步代码块

      同步代码块的格式:

        synchronized(锁对象){

          需要被同步的代码...

        }

同步代码块要注意的事项:

  1. 任意的一个对象都可以作为锁对象
  2. 在同步代码块中调用了sleep方法并不是释放锁对象的,也就是不会改变锁对象的开关状态,就像你睡觉锁着门,别人也进不来
  3. 只有真正存在线程安全问题的时候才使用同步代码块,否则会降低效率的
  4. 多线程操作的锁对象必须是唯一共享的,否则无效。
public class Demo9 {public static void main(String[] args) {// TODO Auto-generated method stub//创建三个线程对象,模拟三个窗口SaleTicket thread1=new SaleTicket("窗口1");SaleTicket thread2=new SaleTicket("窗口2");SaleTicket thread3=new SaleTicket("窗口3");//开启线程售票
        thread1.start();thread2.start();thread3.start();}}
class SaleTicket extends Thread{static int num=50;//票数        不加static的时候是非静态的成员变量,非静态的成员变量数据是在每个对象中都会维护一份数据的。所以会出现三个窗口卖了150张票的情况static Object o=new Object();//为什么要加static呢public SaleTicket() {}public SaleTicket(String name) {// TODO Auto-generated constructor stubsuper(name);}@Overridepublic void run() {// TODO Auto-generated method stubwhile (true) {//同步代码块synchronized (o) {//可以使用字符串   "锁"   ,这是最简单的锁对象,因为它在字符串常量池中if (num>0) {System.out.println(Thread.currentThread().getName()+"售出了第"+num+"号票");num--;}else {System.out.println("售罄了...");break;}}}//super.run();
    }
}结果:
窗口1售出了第50号票
窗口1售出了第49号票
窗口1售出了第48号票
窗口1售出了第47号票
窗口3售出了第46号票
窗口3售出了第45号票
窗口3售出了第44号票
窗口3售出了第43号票
窗口3售出了第42号票
窗口3售出了第41号票
窗口3售出了第40号票
窗口3售出了第39号票
窗口3售出了第38号票
窗口2售出了第37号票
窗口2售出了第36号票
窗口2售出了第35号票
窗口2售出了第34号票
窗口2售出了第33号票
窗口2售出了第32号票
窗口2售出了第31号票
窗口2售出了第30号票
窗口2售出了第29号票
窗口2售出了第28号票
窗口2售出了第27号票
窗口2售出了第26号票
窗口2售出了第25号票
窗口2售出了第24号票
窗口2售出了第23号票
窗口2售出了第22号票
窗口2售出了第21号票
窗口2售出了第20号票
窗口2售出了第19号票
窗口2售出了第18号票
窗口2售出了第17号票
窗口2售出了第16号票
窗口2售出了第15号票
窗口2售出了第14号票
窗口2售出了第13号票
窗口2售出了第12号票
窗口2售出了第11号票
窗口2售出了第10号票
窗口2售出了第9号票
窗口2售出了第8号票
窗口2售出了第7号票
窗口2售出了第6号票
窗口2售出了第5号票
窗口2售出了第4号票
窗口2售出了第3号票
窗口2售出了第2号票
窗口2售出了第1号票
售罄了...
售罄了...
售罄了...

    方式二:同步函数

转载于:https://www.cnblogs.com/zhangwugai/p/10354537.html

Java学习笔记(13)相关推荐

  1. java学习笔记(13) 第13章 - 常用类

    第13 章常用类-目录 13.1 包装类 13.1.1 包装类的分类.包装类和基本数据的转换.案例演示.课堂测试 13.1.2 包装类型和String 类型的相互转换 13.1.3 Integer 类 ...

  2. java学习笔记13:正则表达式、System类、Date类、Calendar类

    一.正则表达式 1.概述:是指一个用来描述或者匹配一系列符合某个句法规则的字符串:其实就是一种规则,有自己特殊的应用. 2.正则表达式的组成规则 (1).字符 表达式 代表含义 x 字符 x.举例:' ...

  3. Java学习笔记13

    Object类是所有类.数组.枚举类的父类,是类层次结构的根类.每个类都使用Object作为超类.所有对象(包括 数组)都实现这个类的方法. Object类实现了以下方法: 我们来看看源码中hashC ...

  4. Java学习笔记13(equals()方法;toString()方法)

    equals()方法: equals方法是Object类中的方法:Object是所有类的祖宗,所以所有类都有equals()方法: boolean equals(Object obj); equals ...

  5. java 量化指标_量化投资学习笔记13——各种指标的绘图、计算及交易策略

    <量化投资:以python为工具>第五部分笔记 先来画k线图,要注意finance模块已经从matplotlib库中去除,现在要用mpl_finance库,单独安装. 其中有candles ...

  6. mybatis学习笔记(13)-延迟加载

    2019独角兽企业重金招聘Python工程师标准>>> mybatis学习笔记(13)-延迟加载 标签: mybatis [TOC] resultMap可以实现高级映射(使用asso ...

  7. java学习笔记十三

    11. 凡是继承了FilterOutputStream或FilterInputStream的类都是过滤流,也就是说他们不能直接跟目标(键盘,文件,网络等,节点流可以)数据打交道,只能包装 Intput ...

  8. 【Java学习笔记之二十六】深入理解Java匿名内部类

    在[Java学习笔记之二十五]初步认知Java内部类中对匿名内部类做了一个简单的介绍,但是内部类还存在很多其他细节问题,所以就衍生出这篇博客.在这篇博客中你可以了解到匿名内部类的使用.匿名内部类要注意 ...

  9. Java学习笔记22:并发(2)

    Java学习笔记22:并发(2) 图源:PHP中文网 终止任务 终止线程有一种非常简单的方式:设置一个多线程共享的标记位,子线程用轮询的方式检查这个标记位,如果该标记位显示取消状态,就让子线程退出执行 ...

  10. 【java学习笔记day01】运行第一个程序Helloworld!

    java学习笔记day01 2.什么是软件工程师? 3.什么是软件? 4.开发软件需要计算机编程语言,计算机编程语言有很多,例如 c, c++,Java,NET,c#,php... 5.Java软件工 ...

最新文章

  1. 查看CPU是i386架构和x86_64架构
  2. 2021-06-29快速找出Excel表格中两列数据不同内容的3种方法!
  3. 实验中遇到的Quartus II的Warning的解释、原因以及解决方法
  4. 查看go 安装了哪些包_如何灵活地进行 Go 版本管理
  5. python写算法太慢_程序运行慢?你怕是写的假 Python
  6. linux 汇编 读取软盘,Linux下如何格式化软盘和读取软盘?
  7. ai可以滚轮缩放吗_AI侵入艺术天堂!艺术也可以“量产”了吗?
  8. 剑指offer:按之字形打印二叉树(栈|双向队列+中序遍历)
  9. go在ubuntu下安装
  10. 机器学习建模商务合作
  11. 宽度学习详解(Broad Learning System)
  12. 投资理财之基金四:指数基金
  13. 转 localStorage
  14. Github+Typora+PicGo+Jsdelivr 实现白P图床
  15. Scene(场景)的使用
  16. 佩尔(Pell)方程最小正整数解
  17. 虚拟存储器与虚拟内存
  18. 如何用NAS打造私有协同办公系统?
  19. Minecraft开服ipv6配置
  20. Android使用Shape实现简单的三角和圆形等

热门文章

  1. LeetCode (二分小专题)33搜索旋转排序数组34在排序数组中查找元素的第一个和最后一个位置35搜索插入位置
  2. php mysql db封装类_封装自己的DB类(PHP)
  3. jar打包 剔除第三方依赖以及它的依赖_maven打包成第三方jar包且把pom依赖包打入进来的方法...
  4. keras cnn注意力机制_从发展历史视角解析Transformer:从全连接CNN到Transformer
  5. 记一次fastjson转jackson的生产事故
  6. 2018高中计算机会考知识点,2018高中物理会考知识点总结
  7. 区块链和同态加密结合使用的电子投票系统_全同态加密资源汇总
  8. springboot图书管理怎么实现借书时间到期提醒_今日图书丨有了这个,图书管理再也没烦恼!...
  9. 这些基础协议,你懂吗?
  10. 【干货】网管的三个重要服务:AAA、NTP和SYSLOG