在Java创建多个可变大小对象池
对象池模式是一种软件创建设计模式,用于初始化类实例的成本非常高的情况。基本上,对象池是一个包含一定数量对象的容器。所以,当一个对象从池中取出时,它在池中不可用,直到它被放回。
池中的对象有一个生命周期:
- 创建
- 验证
- 破坏。
对象池可以提供很大的速度提升;当初始化一个类实例的成本很高,实例化的速度很高,并且在任何给定时刻使用的实例化数量很低时,它的效果最好。
当对象构建成本高且只需要使用很短的时间时,对象池设计很有用。在这种设计模式中,我们跟踪哪些实例化对象正在使用中,哪些是可访问的。
如何创建多个对象池?
我们都知道如何创建单个对象池。但是可能需要创建多个可变大小的对象池。这意味着我们可以有多个池,而不是创建单个对象池 o 固定大小,并且每个池具有不同数量的总对象。
它的实时性要求是什么?
可以通过生成多个可变大小的内存池来完成错误处理或编程中紧急情况下所需的内存分配。
有一些物体的新物体的生产似乎稍微贵一些,因为它们不被认为是轻量级的。数据库连接对象、解析器对象、线程生成等都是示例。我们可能必须在任何应用程序中构建大量这样的对象池。由于此类对象的生成成本很高,因此会对任何程序的性能产生负面影响。我们可以一次又一次地使用同一个对象。
执行:
我们在这里创建了一个“线程”类,它的对象在池中,另一个类“线程池”用于创建多个“线程”对象池。
在我们的班级 Thread 班级(班级 1)
我们有数据成员:
- “uniqueId” 存储为每个线程对象生成的唯一 ID。
- “name” 保留线程对象的名称。
在我们的类ThreadPool类(类2)
我们有数据成员:
- isFirst = true 最初保持为真,每当创建池中的第一个线程对象时,在创建第一个对象后,它都会设置为 false。
- Thread 类型的 myThreads[] 是一个数组引用,将引用线程类对象(线程池数组)
- isUsed[] 布尔类型,它是一个数组,用于跟踪当前正在使用的线程对象
- noOfThreadPools 来计算线程池的数量 & 是一个类级别的属性
- ThreadreferenceCount 用于计算特定池中的线程引用数
- poolNum 存储分配给每个创建的池的唯一编号
例子
Java
// Java Program to Creating Multiple Pools Of Objects of
// Variable Size
// Importing required classes
import java.io.*;
import java.util.*;
// Class 1
// Helper class
class Thread {
// Members of this class
private int uniqueId;
private static int uniqueIDGen = 0;
private String thread_name;
// Constructor that initializes the objects of Thread
// class
Thread() { uniqueId = generateUniqueId(); }
// Method 1
// To set the value of the data member,
// name of the Thread's Object
public void setNameOfThread(String name)
{
thread_name = name;
}
// Method 2
public String getNameOfThread() { return thread_name; }
// Method 3
// To generate a unique id for each Thread's Object
private int generateUniqueId() { return uniqueIDGen++; }
// Method 4
// To Compare that the "this" reference and
// "t1" reference refer to same object
public boolean compare(Thread t1)
{
if (t1.uniqueId == this.uniqueId) {
return true;
}
else {
return false;
}
}
}
// Class 2
// Helper class
class ThreadPool {
// member variables of this class
// To keep true whenever 1st object of a pool is
// created,
// after 1st object creation, it is set to false
private boolean isFirst = true;
// Array reference of myThread (Thread Pool Array)
private Thread myThreads[] = null;
// Array to Keep track that which Thread's objects
// are in use currently
private boolean isUsed[] = null;
private int n;
// To keep count of no of Thread Pools and
// is a class level Property
private static int noOfThreadPools = 0;
// Keeping count of no of thread references
// in a particular pool
private int ThreadreferenceCount = 0;
// To Give a unique number to every Pool Created
private int poolNum = 0;
// Constructor of class 2
public ThreadPool()
{
noOfThreadPools++;
poolNum = noOfThreadPools;
}
// Method 1
// To give "size" of each Thread pool and
// creating size no of objects of Thread Type,
// returning true if successful, else false
public boolean initialize(int size)
{
boolean status = false;
if (true == isFirst) {
isFirst = false;
n = size;
// Assign memory of reference of array
// using new keyword
myThreads = new Thread[n];
for (int i = 0; i < n; i++) {
// Creating new object in heap of Thread
// Class & myThread[i] reference refer it
myThreads[i] = new Thread();
// we are assigning thread name to each
// thread
String name = Integer.toString(i + 1);
name = name.concat(
" is the thread number of the pool ");
name = name.concat(
Integer.toString(poolNum));
// Name assigning finishes
myThreads[i].setNameOfThread(name);
}
// Creating new array of boolean type which is
// referred by isUsed reference
isUsed = new boolean[n];
for (int i = 0; i < n; i++) {
// Now making isUsed false for all the
// references false,
// false because when initializing, no
// reference from outside is referring to
// any of the objects created (from o to
// size-1)
isUsed[i] = false;
}
status = true;
}
return status;
}
// Method 2
// To get reference of the Thread Objects Present in the
// Pool If no object is free, it returns null
public Thread getReference()
{
Thread threadToReturn = null;
if (ThreadreferenceCount < n) {
for (int i = 0; i < n; i++) {
// When no reference from outside the class
// is referring to object myThread[i],
// isUsed[i] is false
if (false == isUsed[i]) {
threadToReturn = myThreads[i];
// Make isUsed[i] as true because we are
// returning a reference to the object
// referred by myThread[i]
isUsed[i] = true;
// Incrementing the count because we are
// returning a reference to the object
// referred by myThread[i] to outside
// world now this object cant be referred
// by another reference from outside
ThreadreferenceCount++;
// Break keyword
break;
}
}
}
return threadToReturn;
}
// Method 3
// To release the outside world reference;
// Here : "thread" - passed as parameter
public void releaseReference(Thread thread)
{
if (ThreadreferenceCount > 0) {
for (int i = 0; i < n; i++) {
// Compare the "thread" parameter with every
// reference and release the matched one by
// making isUsed[i] = false;
if (true == thread.compare(myThreads[i])) {
// Make isUsed[i] is false to show no
// reference from
// outside the class is referring to
// object myThread[i]
isUsed[i] = false;
// Decrementing the count because we are
// releasing a reference to the object
// in outside world
ThreadreferenceCount--;
break;
}
}
}
}
// Method 4
// To make all the objects free for garbage collection
// To restore to initial situation
public boolean deInitialize()
{
boolean status = false;
if (isFirst = false) {
status = true;
}
// This condition is not required if one wants to
// deinitialize() even if the references are present
// outside
else if (ThreadreferenceCount == 0) {
for (int i = 0; i < n; i++) {
myThreads[i] = null;
}
myThreads = null;
isUsed = null;
n = 0;
isFirst = true;
status = true;
}
return status;
}
}
// Class 3
// Min class
public class Main {
// Main driver method
public static void main(String[] args)
{
// Display message on console for better readability
System.out.println(
"*****************POOL1 Of Threads Created*****************");
// Creating object of class 2 in class 3 main()
// method
ThreadPool p1 = new ThreadPool();
// Creating pool of 2 objects
if (p1.initialize(2)) {
System.out.println("Pool 1 initialized");
}
else {
System.out.println("Pool 1 not initialized");
}
// Now getting 2 references to the 2 Objects from
// this pool
// Thread 1
Thread t1 = p1.getReference();
if (t1 != null) {
System.out.println(t1.getNameOfThread());
}
else {
System.out.println(
" t1 do not refer any object");
}
// Thread 2
Thread t2 = p1.getReference();
if (t2 != null) {
System.out.println(t2.getNameOfThread());
}
else {
System.out.println(
" t2 do not refer any object");
}
// Thread 3
Thread t3 = p1.getReference();
if (t3 != null) {
System.out.println(t3.getNameOfThread());
}
else {
System.out.println(
" t3 do not refer any object");
}
// Releasing all the references of pool 1
p1.releaseReference(t1);
t1 = null;
p1.releaseReference(t2);
t2 = null;
// As we have not used deInitialize() method, we
// cannot initialize the pool p1 again
if (p1.initialize(2)) {
// Print statement
System.out.println("Pool 1 initialized");
}
else {
// Print statement
System.out.println(
"Pool 1 not initialized as it was already initialized\n");
}
// Creating pool 2
// Display message on console for better readability
System.out.println(
"*****************POOL2 Of Threads Created*****************");
ThreadPool p2 = new ThreadPool();
// Creating pool of 3 objects
p2.initialize(3);
Thread tp1 = p2.getReference();
if (tp1 != null) {
System.out.println(tp1.getNameOfThread());
}
else {
System.out.println(
"tp1 dont refer to any object");
}
// Releasing references of pool 2
p2.releaseReference(tp1);
tp1 = null;
// Deinitializing both the pools
// using deInitialize() method
p1.deInitialize();
p2.deInitialize();
}
}
输出
*****************POOL1 Of Threads Created*****************
Pool 1 initialized
1 is the thread number of the pool 1
2 is the thread number of the pool 1
t3 do not refer any object
Pool 1 not initialized as it was already initialized
*****************POOL2 Of Threads Created*****************
1 is the thread number of the pool 2
输出说明:
- 在这里,我们通过以下方式创建两个线程对象池:
ThreadPool p1 = new ThreadPool() & ThreadPool p2 = new ThreadPool()
- 然后我们在 p1 和 p2 上调用 initialize() 方法,分别给出大小(池中的“线程”对象总数)– 2 和 3。
- 然后创建线程类(t1 和 t2)的 2 个引用,它们引用池 p1 中的对象(线程类型)。
- 创建了 Thread 类的第三个引用(t3),我们试图从池 p1 中获取对象(通过在 p1 上调用 getReference()),以便 t3 可以引用它。但是t3不引用任何对象,因为Pool p1 size是2,只有2个来自外界的引用可以引用池中的2个对象。
- 然后我们通过调用 releaseReference() 方法释放两个引用(t1 和 t2)。现在池中的对象可用,外部世界的引用可以通过调用 p1 上的 getReference() 方法来引用它们。
- 类似地,我们创建了另一个引用 (tp1),但它引用池 p2 中包含的 Thread 对象,因为我们在 p2 上调用了 getReference() 方法。
- 然后我们通过调用方法 releaseReference() 释放引用 (tp1)。
- 最后,我们在 p1 和 p2 上调用 deInitialize() 方法,将 p1 和 p2 池带回到调用 initialize() 之前的起始条件。