iis服务器助手广告广告
返回顶部
首页 > 资讯 > 后端开发 > Python >Java线程池详细解读
  • 192
分享到

Java线程池详细解读

2024-04-02 19:04:59 192人浏览 泡泡鱼

Python 官方文档:入门教程 => 点击学习

摘要

目录1、线程池1.1 线程池概念1.2 线程池的实现2、StringBuffer类面试题:请解释String、StringBuffer、StringBuilder的区别?3、

1、线程池

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

1.1 线程池概念

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

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

image-20210817100145027

追加一个并发访问的程序报: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包

image-20210817171959845

但是日期格式里面需要设置一些日期标记:年(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接口所的来的方法。

image-20210817191154586

实现对象数组的排序


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可以帮助我们进行转码。这种做法非常麻烦,如果要开发国际版本的软件还是自己安装一个编辑软件比较好。

image-20210817212132969

语言配置文件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基础内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!

--结束END--

本文标题: Java线程池详细解读

本文链接: https://www.lsjlt.com/news/133326.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • Java线程池详细解读
    目录1、线程池1.1 线程池概念1.2 线程池的实现2、StringBuffer类面试题:请解释String、StringBuffer、StringBuilder的区别?3、...
    99+
    2022-11-12
  • 超详细讲解Java线程池
    目录池化技术池化思想介绍池化技术的应用如何设计一个线程池Java线程池解析ThreadPoolExecutor使用介绍内置线程池使用ThreadPoolExecutor解析整体设计线...
    99+
    2022-11-12
  • java线程池详解
    线程池概述 线程池就是一个管理线程的池子,可以降低创建和销毁线程带来的资源消耗因为线程其实也是一个对象,创建一个对象,需要经过类加载过程,销毁一个对象,需要走GC垃圾回收流程,都是需要资源开销的。 提高响应速度,任务到达了相对于从线程池取线...
    99+
    2015-04-06
    java基础 线程池 java
  • Java线程池 ThreadPoolExecutor 详解
    目录一 为什么要使用线程池二 线程池原理详解2.1 线程池核心组成2.2 Execute 原理三 线程池的使用3.1 创建线程池3.1.1 自定义线程池3.1.2 功能线程池3.1....
    99+
    2022-11-13
  • Java多线程与优先级详细解读
    目录1、多线程1.1多线程的基本概念1.2多线程的实现1.3继承Thread类实现多线程1.4Runnable接口实现多线程1.5Thread类和Runnable接口实现多线程的区别...
    99+
    2022-11-12
  • 图文详解Java线程和线程池
    目录一、什么是线程,线程和进程的区别是什么二、线程中的基本概念,线程的生命周期三、单线程和多线程四,线程池的原理解析五,常见的几种线程池的特点以及各自的应用场景总结一、什么是线程,线...
    99+
    2022-11-12
  • Java线程池Executor用法详解
    目录线程池类图线程池的好处new Thread的弊端线程池核心类-ThreadPoolExecutor使用Executors创建线程池Executors.newCachedThrea...
    99+
    2022-11-13
    Java 线程池 Java Executor Java 线程池 Executor
  • JAVA多线程详解(超详细)
    目录 一、线程简介1、进程、线程2、并发、并行、串行3、进程的三态 二、线程实现1、继承Thread类2、实现Runnable接口3、实现Callable接口(不常用) 三、线程常用方法1、线程的状态2、线程常用方法 四...
    99+
    2023-08-19
    java jvm 开发语言
  • Java线程池7个参数的详细含义
    目录一、corePoolSize 线程池核心线程大小二、maximumPoolSize 线程池最大线程数量三、keepAliveTime 空闲线程存活时间四、unit 空闲线程存活时...
    99+
    2022-11-13
  • java线程池核心API源码详细分析
    目录概述源码分析ExecutorExecutorServiceScheduledExecutorServiceThreadPoolExecutorScheduledThreadPoo...
    99+
    2022-11-13
  • Java多线程之线程池七个参数详解
    目录corePoolSize:核心线程数maximumPoolSize:最大线程数keepAliveTime:空闲线程存活时间unit:时间单位workQueue:工作队列threa...
    99+
    2022-11-12
  • 详解Java如何关闭线程以及线程池
    目录前言1. 关闭线程1.1 volatile关键字1.2 intrrrupt()方法2.关闭线程池2.1 shutdownNow()方法2.2 shutdown()方法前言 这个问...
    99+
    2022-11-13
  • Java多线程编程详细解释
    目录一、多线程的优缺点多线程的优点:多线程的代价:二、创建java多线程1、创建Thread的子类2、实现Runnable接口三、线程安全四、java同步块五、java线程通信六、j...
    99+
    2022-11-12
  • 详解Java并发包中线程池ThreadPoolExecutor
    目录一、线程池简介二、ThreadPoolExecutor类2.1、ThreadPoolExecutor成员变量以含义2.2、ThreadPoolExecutor的参数以及实现原理2...
    99+
    2022-11-12
  • java线程池详解及代码介绍
    目录一.线程池简介二、四种常见的线程池详解三、缓冲队列BlockingQueue和自定义线程池ThreadPoolExecutor总结一.线程池简介 线程池的概念 线程池就是首先创...
    99+
    2022-11-12
  • Java 线程池全面总结与详解
    目录原理阻塞队列有界阻塞队列无界阻塞队列同步移交队列实现类分析使用Executors创建线程池线程池关闭线程池是很常用的并发框架,几乎所有需要异步和并发处理任务的程序都可用到线程池。...
    99+
    2022-11-12
  • 详细解读Java Spring AOP
    一、对AOP的初印象 首先先给出一段比较专业的术语(来自百度): 在软件业,AOP为Aspect Oriented Programming的缩写,意为:面向切面编程,通过预编译方式...
    99+
    2022-11-12
  • java线程池的四种创建方式详细分析
    目录前言1. 线程池2. 创建方式前言 在讲述线程池的前提 先补充一下连接池的定义 连接池是创建和管理一个连接的缓冲池的技术,这些连接准备好被任何需要它们的线程使用 可以看到其连接池...
    99+
    2022-11-13
  • 线程池是什么?线程池(ThreadPoolExecutor)使用详解
    点一点,了解更多https://www.csdn.net/ 本篇文章将详细讲解什么是线程池,线程池的参数介绍,线程池的工作流程,使用Executors创建常见的线程池~~~ 目录 点一点,了解更多 文章目录 一、线程池的概念 1.1线...
    99+
    2023-09-03
    java 数据结构 jvm 面试 java-ee
  • Java线程池的分析和使用详解
    目录1.   引言2.线程池的使用线程池的创建线程池的关闭3.   线程池的分析4.   合...
    99+
    2022-11-12
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作