# Day13-Java基础

Posted zsr6135

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了# Day13-Java基础相关的知识,希望对你有一定的参考价值。

Day13-Java

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 finalizeday06-jsp

DAY13JAVA第十三天I/O学习笔记

Java入门提高篇Day13 Java中的反射机制

[vscode]--HTML代码片段(基础版,reactvuejquery)

[Go] 通过 17 个简短代码片段,切底弄懂 channel 基础

AI基础_Day02