Java线程池详细解读

目录
  • 1、线程池
    • 1.1 线程池概念
    • 1.2 线程池的实现
  • 2、StringBuffer类
    • 面试题:请解释String、StringBuffer、StringBuilder的区别?
  • 3、Runtime类
    • 面试题:什么叫gc?如何处理
  • 4、System类
    • 面试题:请解释final、finally、finalize的区别?
  • 5、对象克隆
  • 6、Date类
    • 6.1 日期处理类—Date类
    • 6.2 日期格式化—SimpleDateFormat类(核心)
  • 7、 数字操作类—Math类
    • 7.1 随机数—Random()
    • 7.2 大数字操作类
      • ​ 1.大整数操作类:BigIntegr
      • ​ 2.大小数操作类:BigDcimal
  • 8、Arrays类
  • 9、比较器—Comparable
    • 9.1 Comparable
    • 9.2 二叉树( Binary Tree )
  • 10、国际化

1、线程池

线程池就是多个线程封装在一起操作。

1.1 线程池概念

在生活中经常遇见,今天开发一个项目需要20个人一起开发

  • 这个活很大,有多少人要多少人
  • 这个活很大,但是要求10个人
  • 这个活很大,但只要求1个人做

追加一个并发访问的程序报:java.util.concurrent,对于此线程池的操作的核心类和接口就定义在之中。这里面有两个核心的接口:

  1. 普通的执行线程池定义:Interface ExecutorService
  2. 调度线程池:Interface ScheduledExecutorService
  • 如果要进行线程池的创建一般使用Class Executors这个类
  • 创建无法小限制的线程池:public static ExecutorService newCachedThreadPool()
  • 创建固定大小的线程池:public static ExecutorService newFixedThreadPool(int nThreads)
  • 单线程池:public static ExecutorService newSingleThreadExecutor()
  • 创建定时调度池:public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize)

1.2 线程池的实现

创建无限大小的线程池

package com.day13.demo;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class PoolDemo1 {

	public static void main(String[] args) throws Exception {
		// TODO Auto-generated method stub
		//创建了一个线程池的模型,但是后面没有线程
		ExecutorService executorService = Executors.newCachedThreadPool();
		for (int i = 0; i < 10; i++) {
			int index = i;
			Thread.sleep(200);
			executorService.submit(()-> {
				System.out.println(Thread.currentThread().getName() + ",i = " + index);
			});
		}
		executorService.shutdown();
	}
}

创建固定大小的线程池

package com.day13.demo;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class PoolDemo1 {

	public static void main(String[] args) throws Exception {
		// TODO Auto-generated method stub
		//创建了一个线程池的模型,但是后面没有线程
		ExecutorService executorService = Executors.newFixedThreadPool(3);
		for (int i = 0; i < 10; i++) {
			int index = i;
			Thread.sleep(200);
			executorService.submit(()-> {
				System.out.println(Thread.currentThread().getName() + ",i = " + index);
			});
		}
		executorService.shutdown();
	}
}

创建我们的单线程线程池

package com.day13.demo;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class PoolDemo1 {

	public static void main(String[] args) throws Exception {
		// TODO Auto-generated method stub
		//创建了一个线程池的模型,但是后面没有线程
		ExecutorService executorService = Executors.newSingleThreadExecutor();
		for (int i = 0; i < 10; i++) {
			int index = i;
			executorService.submit(()-> {
				System.out.println(Thread.currentThread().getName() + ",i = " + index);
			});
		}
		executorService.shutdown();
	}
}

定时调度池

package com.day13.demo;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

public class PoolDemo1 {

	public static void main(String[] args) throws Exception {
		// TODO Auto-generated method stub
		//创建了一哥具备有三个线程大小的定时调度池
		ScheduledExecutorService executorService = Executors.newScheduledThreadPool(1);
		for (int i = 0; i < 10; i++) {
			//Thread.sleep(200);
			int index = i;
			executorService.scheduleAtFixedRate(new Runnable(){
				@Override
				public void run() {
					// TODO Auto-generated method stub
						System.out.println(Thread.currentThread().getName() + ",i = " + index);
				}

			}, 3, 2, TimeUnit.SECONDS);//使用的是一个秒的单位,表示3秒后开始执行,而后每过2秒执行一次
		}
	}
}

线程池给我们开发者带来唯一好处的就是允许多个线程按照组的模式进行程序的处理,这样在一个业务逻辑非常复杂的情况下,性能就会得到很好的提升。

2、StringBuffer类

对于类库的学习,不可能全学完。你所需要知道就是如何面对解决问题的方法。要学会查询文档。

StringBuffer类之前首先来简单回顾一下String类的特点:

​ String类的对象有两种实例化方式,一种是直接赋值,只会开辟一块堆内存空间,而且对象可以自动入池,另外一种方式使用构造方法完成,会开辟两块空间,有一块空间将称为垃圾,并且不会自动入池,但是可以通过intern()方法手工入池;

​ 字符串常亮一旦声明则不能改变,而字符串对象可以改变,但是改变的是其内存地址的指向;

通过以上的几个特点就可以清楚的发现,String类是表示字符串使用最多的类,但是其不合适于被频繁修改的字符串操作上,所以在这种情况下,往往可以使用StringBuffer类,即:StringBuffer类方便用户进行内容的修改,在String类之中使用“+”作为数据库的连接操作,而在StringBuffer类之中使用append()方法进行数据的连接。

使用StringBuffer操作,StringBuffer内容可以改变。

package com.day13.demo;

public class BufferDemo {
	public static void main(String[] args) {
		StringBuffer buf = new StringBuffer();
		buf.append("hello").append(",world!");
		fun(buf);//修改了buf的内容
		System.out.println(buf);
	}
	public static void fun(StringBuffer tem){
		tem.append("\n").append("zsr");
	}
}

String和StringBuffer最大的区别就是:String的内容无法修改,而StringBuffer的内容可以修改。但是在开发的选择还是优先选择String类。

现在学习的字符串的操作类就有两个了:String,StringBuffer,那么下面通过这两个类的定义来研究一下关系:

String类: StringBuffer类:
public final class String
extends Object
implements Serializable,Comparable,CharSequence
public final class StringBuffer
extends Object
implements Serializable, CharSequence

可以发现两个类都是“CharSequence”接口的子类。这个接口描述的是字符集,所以串就属于字符集的子类,如果以后看见CharSequence最简单的联想就是字符串。但是有一个小小的问题需要注意一下就是String和StringBuffer两个类型无法直接转换。

利用StringBuffer:利用StringBuffer构造方法、append()方法

将String变为StringBuffer

1.直接利用StringBuffer类的构造方法,public StringBuffer(String str)

package com.day13.demo;

public class BufferTest{
	public static void main(String[] args) throws Exception {
		String str = "Hello World.";
		StringBuffer buf = new StringBuffer(str);
		fun(buf);
		System.out.println(buf);
}
	private static void fun(StringBuffer temp) {
		temp.append("\n").append("zsr");
	}
}

2.利用StringBuffer类的append()方法

package com.day13.demo;

public class BufferTest{
	public static void main(String[] args) throws Exception {
		String str = "Hello World.";
		StringBuffer buf = new StringBuffer();
		buf.append(str);
		fun(buf);
		System.out.println(sb);
	}
	private static void fun(StringBuffer temp) {
		temp.append("\n").append("zsr");
	}
}

将StringBuffer变成String,利用StringBuffer类的toString()方法完成

package com.day13.demo;

public class BufferTest{
	public static void main(String[] args) throws Exception {
		StringBuffer buf = new StringBuffer("hello,World!");
		String str = buf.toString();
		System.out.println(str);
	}
}

实际上StringBuffer还是有一些String类所没有的特点的。

1.字符串反转操作,public StringBuffer reverse()

package com.day13.demo;

public class BufferTest{
	public static void main(String[] args) throws Exception {
		StringBuffer buf = new StringBuffer("hello,World!");
		System.out.println(buf.reverse());
	}
}

2.删除指定范围内的数据,public StringBuffer delete(int start, int end)

package com.day13.demo;

public class BufferDemo {
	public static void main(String[] args) {
		StringBuffer buf = new StringBuffer("Hello,World!");
		System.out.println(buf.delete(5, 11));
    }
}

3.插入数据的方法, public StringBuffer insert(int offset, Object obj)

package com.day13.demo;

public class BufferDemo {
	public static void main(String[] args) {
		StringBuffer buf = new StringBuffer("Hello,World!");
		System.out.println(buf.delete(5,11).insert(0, "你好,"));
	}
}

面试题:请解释String、StringBuffer、StringBuilder的区别?

  • String的内容不可以修改,StringBuffer与StringBuilder内容可以修改
  • StringBuffer采用同步处理属于线程安全操作,StringBuilder采用异步处理属于线程不安全操作。

3、Runtime类

在每一个JVM的进程中,都会存在一个运行时的操作类的对象,而这对象所属的类型就是Runtime类。打开这个类的文档,发现这个类之中并没有构造方法的定义,可是按照之前所学,每个类至少有一个构造方法,而这个类的构造方法实际上存在只是不被外部看见而已,因为构造方法私有化了,这是一个标准的单例设计模式,既然是单例设计模式则在这个类之中一定会存在一个static型方法,可以取得本类的Runtime实例化对象:public static Runtime getRuntime()。

取得了Runtime类之后最主要的功能就是可以通过它来观察当前的内存操作情况:

方法名称 类型 描述
public long freeMemory() 普通 取得当前空余内存空间大小
public long totalMemory() 普通 取得当前可以使用总空间大小
public long maxMemory() 普通 取得最大的可用内存空间的大小
public native void gc() 普通 执行垃圾收集处理

观察一下内存信息的取得

package com.day13.demo;

public class RuntimeDemo {
	public static void main(String[] args) {
		Runtime run = Runtime.getRuntime();
		System.out.println("1、MAX=" + byteToM(run.maxMemory()));
		System.out.println("1、TOTAL=" +  byteToM(run.totalMemory()));
		System.out.println("1、FREE=" +  byteToM(run.freeMemory()));
	}
	public static double byteToM(long num){
		return (double) num / 1024 / 1024;
	}
}

gc垃圾回收

package com.day13.demo;

public class RuntimeDemo {
	public static void main(String[] args) {
		Runtime run = Runtime.getRuntime();
		System.out.println("1、MAX=" + byteToM(run.maxMemory()));
		System.out.println("1、TOTAL=" +  byteToM(run.totalMemory()));
		System.out.println("1、FREE=" +  byteToM(run.freeMemory()));
		String str = "";
		for (int i = 0; i < 2222; i++) {
			str += i;
		}
		System.out.println("2、MAX=" + byteToM(run.maxMemory()));
		System.out.println("2、TOTAL=" +  byteToM(run.totalMemory()));
		System.out.println("2、FREE=" +  byteToM(run.freeMemory()));
		run.gc();//垃圾收集
		System.out.println("3、MAX=" + byteToM(run.maxMemory()));
		System.out.println("3、TOTAL=" +  byteToM(run.totalMemory()));
		System.out.println("3、FREE=" +  byteToM(run.freeMemory()));
	}
	public static double byteToM(long num){
		return (double) num / 1024 / 1024;
	}
}

面试题:什么叫gc?如何处理

  • gc(Garbage Conllector):垃圾收集器,用于释放无用的内存空间
  • gc有两种处理形式,一种是自动不定期调用,另外一种是使用Runtime的gc()方法手工处理调用。

4、System类

实际上在之前进行的数组拷贝就是运用System类中的public static void arraycopy(Object src,int srcPos,Object dest,int destPos,int length)

在这个类中提供有一个取得当前日期时间数的方法**public static long currentTimeMillis();**通过此方法可以取得某一个操作花费的时间。

观察currentTimeMillis()的使用

package com.day13.demo;

public class SystemDemo {
	public static void main(String[] args) {
		long start = System.currentTimeMillis();
		String str = "";
		for (int i = 0; i < 2222; i++) {
			str += i;
		}
		long end = System.currentTimeMillis();
		System.out.println("花费时间:" + (end - start) + "ms");
	}
}

可是在System类之中还存在了一个很有意思的方法:public static void gc(),但是这个gc()方法并不是一个新的gc()方法而是间接调用了一个Runtime类之中的gc()方法,不表示一个重写的方法。

在之前一直强调过一个概念:一个类对象的创建一定要使用构造方法,那么一个对象不使用构造方法了,就一个被释放,被释放的时候一改也有一个方法进行支持才对。所以要想做这种收尾的操作,可以让一个类去覆写object中的finalize()方法。此方法由Object类定义:protected void finalize() throws Throwable。在对象回收之前有可能出现异常或者错误,但是即使出现了也不会影响程序的执行,即:不会因为异常而导致程序的中断执行。

finalize()方法使用

package com.day13.demo;
class Person{
	public Person(){
		System.out.println("问啊娃娃,出来了!");
	}

	@Override
	protected void finalize() throws Throwable {
		// TODO Auto-generated method stub
		System.out.println("我要下地狱了,下辈子不要当人了——");
		throw new Exception("继续要活几千年");
	}

}
public class FinalizeDemo {
	public static void main(String[] args) {
		Person person = new Person();
		person = null;
		System.out.println("已经转世不为人了");
		System.gc();
	}
}

面试题:请解释final、finally、finalize的区别?

  • final是一个关键字,用于定义不能够被继承的父类、不能够覆写的常量
  • finally是异常处理的统一出口
  • finalize是Object类中的方法,用于在对象回收前进行调用

5、对象克隆

克隆就是对象复制的一个概念,不过这种概念一般使用的比较少,因为很少有人去复制已经存在的对象。Object类本身就支持对象克隆方法。可以发现protected Object clone() throws CloneNotSupportedException;我们要想实现克隆,那么我们并不是所有类的对象可以随便克隆,需要被克隆的对象所在类一定要实现Cloneable接口,而最关键的是该接口并没有任何的抽象方法,所以该接口只是一个标识接口,表示一种能力。

对象克隆实现

package com.day13.demo;
class Per implements Cloneable{//必须实现此接口
	private String name;
	private int age;
	public Per(String name, int age) {
		super();
		this.name = name;
		this.age = age;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public int getAge() {
		return age;
	}
	public void setAge(int age) {
		this.age = age;
	}
	@Override
	public String toString() {
		return "Per [name=" + name + ", age=" + age + "]";
	}
	@Override
	//覆写权限扩大  protected 扩大到 public
	public Object clone() throws CloneNotSupportedException {
		// TODO Auto-generated method stub
		return super.clone();//父类负责克隆
	}
}
public class CloneDemo {
	public static void main(String[] args) throws Exception{
		 Per perA = new Per("kaco",12);
		 //perA.clone();不能在这写的原因是因为此方法是protected权限 只能在不同包的子类中实现此方法
		 Per perB = (Per) perA.clone();
		 perB.setAge(100);
		 System.out.println(perA);
		 System.out.println(perB);
	}
}

意义不大,需要清楚表示接口的作用,表示的是一个能力。

6、Date类

日期数据类型一定要重视,所有的开发必定要有日期。

6.1 日期处理类—Date类

java.util.data类是在整个程序处理之中唯一可以取得日期当前日期实例化对象的操作方法,也就是说我们要取出当前日期输出Date类对象即可。

package com.day13.demo;

import java.util.Date;

public class DateDemo1 {
	public static void main(String[] args) {
		Date date = new Date();
        //Tue Aug 17 17:01:50 CST 2021
		System.out.println(date);
	}
}

在Date类中最需要关心的一个核心问题:long可以描述日期,看了一通过Date类中提供的方法来进行观察。

方法名称 类型 描述
public Date(long date) 普通 将long类型变为Date类型数据
public long getTime() 普通 将Date类型变为long类型数据

观察转化

package com.day13.demo;

import java.util.Date;

public class DateDemo1 {
	public static void main(String[] args) {
		long num = System.currentTimeMillis();
		System.out.println(new Date(num));
		System.out.println(new Date(num).getTime());
	}
}

这中简单的转换在以后的程序开发经常会使用。

6.2 日期格式化—SimpleDateFormat类(核心)

虽然Date可以取得当前的日期时间,但是取出的结构不是我们所喜欢的格式,这时候就需要我们进行格式的转化,使用的是java.text包

但是日期格式里面需要设置一些日期标记:年(YYYY)、月(MM)、日(dd)、时(HH)、分(mm)、秒(ss)、毫秒(SS);

实现日期格式化处理(日期格式化之后是字符串)

package com.day13.demo;

import java.text.SimpleDateFormat;
import java.util.Date;

public class DateDemo1 {
	public static void main(String[] args) {
		Date date = new Date();
		String str = "YYYY-MM-dd HH:mm:ss";
		SimpleDateFormat sdf = new SimpleDateFormat(str);
		String dateFromat = sdf.format(date);
		System.out.println(dateFromat);
	}
}

将字符串变为Date类型

package com.day13.demo;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;

public class DateDemo2 {
	public static void main(String[] args) throws ParseException{
		Date date = new Date();
		System.out.println(date);
		String str = "yyyy-MM-dd HH:mm:ss";
		SimpleDateFormat sdf = new SimpleDateFormat(str);
		//将Date类型转化为字符串类型
		String newdateStirng = sdf.format(date);
		System.out.println(newdateStirng);
		//将字符串转化为Date类型
		Date newdate = sdf.parse(newdateStirng);
		System.out.println(newdate);
	}
}

7、 数字操作类—Math类

在Java.lang.Math类之中定义了所有的于数学有关的基本公式,在这个类之中所有的方法都是static型的方法,强调一个方法:round(),public static long round(double a),表示四舍五入。

package com.day13.demo;

public class MathDemo {
	public static void main(String[] args) {
		System.out.println(Math.round(13.51));
		System.out.println(Math.round(13.5));
		//如果负数小数,没大于0.5都不进位
		System.out.println(Math.round(-13.51));
		System.out.println(Math.round(-13.5));//-13
	}
}

希望可以准确的保存小数位进行处理。

需要保留几位小数

package com.day13.demo;
class MyMath{
	public static double round(double num, int scale){
		return Math.round(num * Math.pow(10, scale)) / Math.pow(10, scale);
	}
}
public class MathDemo {
	public static void main(String[] args) {
        //1234.457
		System.out.println(MyMath.round(1234.4567, 3));
	}
}

7.1 随机数—Random()

Java .util.Random的主要主要作用就是产生随机数,下面通过一个代码来观察就行。

网站开发的随机验证码

package com.day13.demo;

import java.util.Random;

public class RandomDemo {
	public static void main(String[] args) {
		char data [] = new char[]{'a','b','c','d','e'};
		for (int i = 0; i < 4; i++) {
			System.out.print(data[new Random().nextInt(data.length)]);
		}
	}
}

7.2 大数字操作类

如果说现在有两个非常大的数字要进行数学操作,你们认为要怎么做?这个时候数字已经超过了double的范围,那么只能利用字符串来表示,取出每一个字符串变为数字后进行数学计算,这种方式的难度较高,为了解决这种问题,在Java之中提供了两个大数字操作类:java.math包中BigInteger,BigDecimal,而这两个类是属于Number的子类。

​ 1.大整数操作类:BigIntegr

之前已经强调过了,如果数字较大,肯定按照String来处理,所以这一点可以通过Biginteger的构造方法来观察:

​ 构造:public BigInteger(String val);

而且在BigInteger类之中定义了一些基本的数学计算:

​ 加法:public BigInteger add(BigInteger val);

​ 减法:public BigInteger subtract(BigInteger val);

​ 乘法:public BigInteger multiply(BigInteger val);

​ 除法(不保存余数):public BigInteger divide(BigInteger val);

​ 除法(保存余数):public BigInteger divideAndRemainder(BigInteger val)

大数的四则运算

package com.day13.demo;

import java.math.BigInteger;

public class BigAddDemo {
	public static void main(String[] args) {
		BigInteger bigA = new BigInteger("123712487812974891274891274128947891");
		BigInteger bigB = new BigInteger("43895748395789347589347589398");
		System.out.println("加法计算:" + bigA.add(bigB));
		System.out.println("减法计算:" + bigA.subtract(bigB));
		System.out.println("乘法计算:" + bigA.multiply(bigB));
		System.out.println("除法计算:" + bigA.divide(bigB));
		BigInteger result[] = bigA.divideAndRemainder(bigB);
		System.out.println("除法计算:" + result[0] + "." + result[1]);
	}
}

​ 2.大小数操作类:BigDcimal

BigDecimal类表示的是大小数操作类,但是这个类也具备了于之前同样的基本计算方式,而在实际的工作之中,是用这个类最多的情况是进行准确位数的四舍五入操作,如果要完成这一操作需要关心BigDecimal类中的以下定义:

构造:public BigDecimal(double val);

除法:public BigDecimal divide(BigDecimal divisor ,int scale ,int roundingMode);

进位模式:public static final int ROUND_HALF_UP。

四舍五入进位操作

package com.day13.demo;

import java.math.BigDecimal;
//大数进位方法
class MyMath1{
	public static double round(double num, int scale){
		return new BigDecimal(num).divide(new BigDecimal(1), scale, BigDecimal.ROUND_HALF_DOWN).doubleValue();
	}
}
public class BigDecimalDemo {
	public static void main(String[] args) {
		System.out.println(MyMath1.round(2138845.4567, 3));
	}
}

8、Arrays类

排序操作:java.util.Arrays.sort(数组名称),对于Arrays类一直是进行数组排序的操作,类一直进行数组排序的操作,而Arrays类是定义在java.util包下的一个操作类,在这个类之中定义了所有的与数组有关的基本操作:二分查找,拷贝操作,相等判断,填充,变为字符串输出等。

package com.day13.demo;

import java.util.Arrays;

public class ArraysDemo {
	public static void main(String[] args) {
		int dataA[] = new int []{1,2,3,4,5,6};
		int dataB[] = new int []{1,2,3,4,5,6};
		//数组输出
		System.out.println(Arrays.toString(dataA));
		//两个数组进行比较
		System.out.println(Arrays.equals(dataA,dataB));
		//数组二分法查找
		System.out.println(Arrays.binarySearch(dataA, 4)+1);
	}
}

9、比较器—Comparable

9.1 Comparable

对象数组排序:public static void sort(Object[] a)

package com.day13.demo;

import java.util.Arrays;

class Pers{
	private String name;
	private int age;
	public Pers(String name, int age) {
		this.name = name;
		this.age = age;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public int getAge() {
		return age;
	}
	public void setAge(int age) {
		this.age = age;
	}
	@Override
	public String toString() {
		return "Pers [name=" + name + ", age=" + age + "]";
	}
}
public class ComparableDemo {
	public static void main(String[] args) {
		Pers pers[] = new Pers[]{
			new Pers("张三",12),
			new Pers("李四",23),
			new Pers("刘武",54)//对象数组
		};
		Arrays.sort(pers);//要进行对象数组的排序处理
		System.out.println(Arrays.toString(pers));
	}
}

这个时候没有任何的语法错误,即:程序的代码是正确的,但是在程序执行的时候出现了以下的问题:

Exception in thread "main" java.lang.ClassCastException: com.day13.demo.Pers cannot be cast to java.lang.Comparable
	at java.util.ComparableTimSort.countRunAndMakeAscending(ComparableTimSort.java:320)
	at java.util.ComparableTimSort.sort(ComparableTimSort.java:188)
	at java.util.Arrays.sort(Arrays.java:1246)
	at com.day13.demo.ComparableDemo.main(ComparableDemo.java:36)

明确的告诉用户现在发生了“ClassCaseException”,类转换异常,Person类不能变为Comparables实例。

如果要为对象指定比较规则,那么对象所在的类必须实现Comparable接口,下面首先来看一下这个接口的定义:

public interface Comaparable<T>{
	public int compareTo(T o)
}

Stirng类中的compareTo()就属于覆写Comaparable接口所的来的方法。

实现对象数组的排序

package com.day13.demo;

import java.util.Arrays;

class Pers implements Comparable<Pers>{
	private String name;
	private int age;
	public Pers(String name, int age) {
		this.name = name;
		this.age = age;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public int getAge() {
		return age;
	}
	public void setAge(int age) {
		this.age = age;
	}
	@Override
	public String toString() {
		return "Pers [name=" + name + ", age=" + age + "]\n";
	}
	@Override
	public int compareTo(Pers o) {
		// TODO Auto-generated method stub
		//升序排序 如果降序排序将1 和 -1 进行位置调换
		if(this.age > o.age){
			return -1;
		}else if(this.age < o.age){
			return 1;
		}else{
			return 0;
		}
	}
}
public class ComparableDemo {
	public static void main(String[] args) {
		Pers pers[] = new Pers[]{
			new Pers("张三",12),
			new Pers("李四",23),
			new Pers("刘武",54)//对象数组
		};
		Arrays.sort(pers);//要进行对象数组的排序处理
		System.out.println(Arrays.toString(pers));
	}
}

只要是对象数组排序,就必须有Comparable接口。

9.2 二叉树( Binary Tree )

二叉树是一种排序的基本的数据结构,而如果要想为多个对象进行排序,那么就必须可以区分出对象的大小,那么就必须依靠Comparable接口完成。

二叉树的基本原理:取第一个元素作为根节点,之后每一个元素的排列要求:如果比根节点晓得数据放在左子树,如果比根节点大的数据放在右子树,在输出的时候采用中序(左-根-右)遍历的方式完成。

但是不管是何种方式操作,一定要记住,这种数据结构的实现永远都需要依靠节点类,而这个时候的节点类要保存两个节点:左,右。

10、国际化

在java.util.Locale可以找java提供国际化的相关信息

Locale构造:public Locale(String language, String country)

观察区域和语言代码

package com.day13.demo;

import java.util.Locale;

public class LocalDemo {
	public static void main(String[] args) {
		System.out.println(Locale.CHINA);//zh_CN
		System.out.println(Locale.CHINESE);//zh
	}
}
  • 中国Locale:public static final Locale CHINESE
  • 美国Locale:public static final Locale US
  • 取得当前的Locale对象:public static Locale getDefault()

当我们用eclipse打开Message.properties进行编写后不要慌,我们还有一个非常强大的工具在JDK中,CLASSPATH:C:\Program Files\Java\jdk1.8.0_241\bin 自己安装JDK的环境目录下有一个叫native2ascii.exe可以帮助我们进行转码。这种做法非常麻烦,如果要开发国际版本的软件还是自己安装一个编辑软件比较好。

语言配置文件Message.properties

welcome.info = \u5317\u4EAC\u6B22\u8FCE\u4F60\uFF01

测试文件LocaleDemo.java

package com.day13.demo;

import java.util.ResourceBundle;

public class LocaleDemo {
	public static void main(String[] args) {
		//这个时候设置的baseName没有后缀,而且一定要在CLASSPATH之中
		ResourceBundle res = ResourceBundle.getBundle("com.day13.msg.Message");
        //北京欢迎你!
		System.out.println(res.getString("welcome.info"));
	}
}

资源文件的名称就只是 包.名称前缀

到此这篇关于Day13基础不牢地动山摇-Java基础的文章就介绍到这了,更多相关Java基础内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • Day14基础不牢地动山摇-Java基础

    目录 1.定时器 2.UUID类 3.Base64加密处理 加密处理 多次加密 4.ThreadLocal类 5.IO-File类 5.1 基本操作 5.2 取得文件信息 5.3 综合案例:目录列表 6.IO- 字节流与字符流 6.1 字节输出流:OutputStream 6.2 字节输入流:InputStream 6.3 字符输出流:Writer 6.4 字符输入流:Reader 6.5 字节流与字符流区别 7.转换流 1.定时器 推动整个计算机硬件的发展的核心关键性技术就是时钟.所以在企业开

  • Day15基础不牢地动山摇-Java基础

    目录 1.字符编码 1.1 常用字符编码 1.2 乱码产生分析 2.内存流基本操作 3.打印流 3.1 格式化文本信息 4. System类 4.1 系统输出 4.2 系统输出 4.3 系统输入 5.BufferedReader类 6.Scanner 7.对象序列化 7.1 对象序列化的概念 7.2 实现序列化和反序列化 7.3 transient关键字(了解) 1.字符编码 1.1 常用字符编码 在计算机的世界之中,所有的显示文字都是按照其指定的数字编码进行保存的,如果没有正确的解码,那么就坑

  • Java设计模式之代理模式详细解读

    目录 Java设计模式-代理模式 什么是代理模式? 代理模式-UML图: 源代码: 运行结果: 总结: 应用实例: 优点: 缺点: 使用场景: Java设计模式-代理模式 什么是代理模式? 在代理模式(Proxy Pattern)中,一个类代表另一个类的功能.这种类型的设计模式属于结构型模式. 在代理模式中,我们创建具有现有对象的对象,以便向外界提供功能接口. 所谓的代理严格来讲就是两个子类共同实现一个接口,其中一个子类负责真实业务实现,另一个辅助完成主类业务逻辑操作. 代理模式-UML图: 源

  • Day10基础不牢地动山摇-Java基础

    目录 1.异常的捕获与处理 1.1 处理异常 1.2 异常处理的流程 1.3 throw关键字 1.4 异常处理模型 1.5 RuntimeException 1.6 断言:assert 1.7 自定义异常 2.链表 2.1 链表基本的结构 2.2 链表实现结构说明 2.3 增加链表数据-public void add(数据) 2.4 增加多个数据-public void addAll(数据数组) 2.5 统计数据个数-public int size() 2.6 链表数据转换为对象数组-publ

  • 一篇文章带你深入了解javaIO基础

    目录 一.认识IO 1.IO的分类 2.IO的方式 3.IO读写的方式 4.IO的特性 二.文件操作 1.文件的构成 2.文件的创建 3.文件操作的API使用 三.IO流 1.流的分类 2.流的创建 3.流的使用 <1>输入流 <2>输出流 <3>实例:文件的复制 总结 一.认识IO 1.IO的分类 (1)BIO:同步阻塞IO (2)NIO:同步非阻塞IO (3)AIO:异步阻塞IO 注意: 这里主要介绍BIO 2.IO的方式 IO本质就是对数据的操作 (1)网络IO

  • Day16基础不牢地动山摇-Java基础

    目录 1.反射机制 1.1 认识反射 1.2 取得父类信息 1.3 反射调用构造 1.4 反射调用方法 1.5 反射调用成员 1.6 反射与简单Java类-单级VO操作原理 1.7 单极自动VO设置实现 1.8 反射与简单Java类-多级VO设置实现 2.ClassLoader类加载器 2.1 认识类加载器 2.2 自定义ClassLoader 1.反射机制 反射机制如果只是针对普通开发者而言意义不大,一般都是作为一些系统的构架设计去使用的,包括以后学习的开源框架,那么几乎都是反射机制. 1.1

  • Java线程池详细解读

    目录 1.线程池 1.1 线程池概念 1.2 线程池的实现 2.StringBuffer类 面试题:请解释String.StringBuffer.StringBuilder的区别? 3.Runtime类 面试题:什么叫gc?如何处理 4.System类 面试题:请解释final.finally.finalize的区别? 5.对象克隆 6.Date类 6.1 日期处理类-Date类 6.2 日期格式化-SimpleDateFormat类(核心) 7. 数字操作类-Math类 7.1 随机数-Ran

  • 深入理解Java线程池从设计思想到源码解读

    线程池:从设计思想到源码解析 前言初识线程池线程池优势线程池设计思路 深入线程池构造方法任务队列拒绝策略线程池状态初始化&容量调整&关闭 使用线程池ThreadPoolExecutorExecutors封装线程池 解读线程池execute()addWorker()Worker类runWorker()processWorkerExit() 前言 各位小伙伴儿,春节已经结束了,在此献上一篇肝了一个春节假期的迟来的拜年之作,希望读者朋友们都能有收获. 根据穆氏哲学,投入越多,收获越大.我作此文时

  • 深入了解Java线程池:从设计思想到源码解读

    目录 为什么需要线程池 线程池设计思路 线程池的工作机制 线程池的参数及使用 线程池的状态 提交任务 任务队列 线程工厂 拒绝策略 关闭线程池 Executors 静态工厂 合理地配置线程池 线程池的监控 源码分析 execute addWorker Worker runWorker getTask processWorkerExit 面试题 为什么需要线程池 我们知道创建线程的常用方式就是 new Thread() ,而每一次 new Thread() 都会重新创建一个线程,而线程的创建和销毁

  • 详细分析JAVA 线程池

    系统启动一个新线程的成本是比较高的,因为它涉及与操作系统交互.在这种情形下,使用线程池可以很好地提高性能,尤其是当程序中需要创建大量生存期很短暂的线程时,更应该考虑使用线程池. 与数据库连接池类似的是,线程池在系统启动时即创建大量空闲的线程,程序将一个 Runnable 对象或 Callable 对象传给线程池,线程池就会启动一个线程来执行它们的 run() 或 call() 方法,当 run() 或 call() 方法执行结束后,该线程并不会死亡,而是再次返回线程池成为空闲状态,等待执行下一个

  • 超详细讲解Java线程池

    目录 池化技术 池化思想介绍 池化技术的应用 如何设计一个线程池 Java线程池解析 ThreadPoolExecutor使用介绍 内置线程池使用 ThreadPoolExecutor解析 整体设计 线程池生命周期 任务管理解析 woker对象 Java线程池实践建议 不建议使用Exectuors 线程池大小设置 线程池监控 带着问题阅读 1.什么是池化,池化能带来什么好处 2.如何设计一个资源池 3.Java的线程池如何使用,Java提供了哪些内置线程池 4.线程池使用有哪些注意事项 池化技术

  • java线程池核心API源码详细分析

    目录 概述 源码分析 Executor ExecutorService ScheduledExecutorService ThreadPoolExecutor ScheduledThreadPoolExecutor 总结 概述 线程池是一种多线程处理形式,处理过程中将任务添加到队列,然后在创建线程后自动启动这些任务.线程池线程都是后台线程.每个线程都使用默认的堆栈大小,以默认的优先级运行,并处于多线程单元中.如果某个线程在托管代码中空闲(如正在等待某个事件),则线程池将插入另一个辅助线程来使所有

  • Java线程池7个参数的详细含义

    目录 一.corePoolSize线程池核心线程大小 二.maximumPoolSize线程池最大线程数量 三.keepAliveTime空闲线程存活时间 四.unit空闲线程存活时间单位 五.workQueue工作队列 六.threadFactory线程工厂 七.handler拒绝策略 java多线程开发时,常常用到线程池技术,这篇文章是对创建java线程池时的七个参数的详细解释. 从源码中可以看出,线程池的构造函数有7个参数 这 7 个参数分别是: corePoolSize:核心线程数. m

  • 非常适合新手学生的Java线程池超详细分析

    目录 线程池的好处 创建线程池的五种方式 缓存线程池CachedThreadPool 固定容量线程池FixedThreadPool 单个线程池SingleThreadExecutor 定时任务线程池ScheduledThreadPool ThreadPoolExecutor创建线程池(十分推荐) ThreadPoolExecutor的七个参数详解 workQueue handler 如何触发拒绝策略和线程池扩容? 线程池的好处 可以实现线程的复用,避免重新创建线程和销毁线程.创建线程和销毁线程对

  • java线程池的四种创建方式详细分析

    目录 前言 1. 线程池 2. 创建方式 前言 在讲述线程池的前提 先补充一下连接池的定义 连接池是创建和管理一个连接的缓冲池的技术,这些连接准备好被任何需要它们的线程使用 可以看到其连接池的作用如下: 1. 线程池 线程池(英语:thread pool):一种线程使用模式.线程过多会带来调度开销,进而影响缓存局部性和整体性能.而线程池维护着多个线程,等待着监督管理者分配可并发执行的任务.这避免了在处理短时间任务时创建与销毁线程的代价.线程池不仅能够保证内核的充分利用,还能防止过分调度 特点:

  • 一文带你深入剖析Java线程池的前世今生

    目录 由线程到线程池 线程在做什么 为什么需要线程池 线程池实现原理 总结 由线程到线程池 线程在做什么 灵魂拷问:写了那么多代码,你能够用一句话简练描述线程在干啥吗? public class Demo01 {   public static void main(String[] args) {     var thread = new Thread(() -> {       System.out.println("Hello world from a Java thread"

随机推荐