概念
典型应用是:String 常量池; 并不完全是对象池化技术;对象池更多的是从对象复用出发,考虑的是复用问题;对于调用方client来说,从池中 取到a对象还是b对象没有任何区别; 享元模式强调的是对象的共享;强调内部状态和外部状态的概念;对调用方来说需要根据外部状态取到需要复用的对象; 内部状态不会随环境改变而改变; 会有线程安全的问题需要额外处理;
demo
由于实在找不到合适的例子;网上的案例我 get 不到他们说的点;不知道他们的例子实际应用中能解决什么问题; 我引用《设计模式之禅》中对于使用享元模式的案例:报考系统 oom 的问题解决方案使用的享元模式; 我在原基础上加一些线程安全的代码;
package designpattern;
import java. io. IOException;
import java. util. HashMap;
import java. util. concurrent. CountDownLatch;
import java. util. concurrent. LinkedBlockingDeque;
import java. util. concurrent. ThreadFactory;
import java. util. concurrent. ThreadPoolExecutor;
import java. util. concurrent. TimeUnit;
import java. util. concurrent. atomic. AtomicInteger;
public class Flyweight {
public static void main ( String[ ] args) {
for ( int i = 0 ; i < 4 ; i++ ) {
String subject = "科目" + i;
for ( int j = 0 ; j < 30 ; j++ ) {
String key = subject + "考试地点" + j;
SignInfoFactory. getSignInfo ( key) ;
}
}
concurrentAccess ( ) ;
}
private static void concurrentAccess ( ) {
ThreadPoolExecutor executor = new ThreadPoolExecutor (
Runtime. getRuntime ( ) . availableProcessors ( ) ,
Runtime. getRuntime ( ) . availableProcessors ( ) * 4 ,
10 , TimeUnit. SECONDS, new LinkedBlockingDeque < > ( 30 ) ,
new CustomThredFactory ( "flyweight" )
) ;
CountDownLatch countDownLatch = new CountDownLatch ( 30 ) ;
for ( int j = 0 ; j < 30 ; j++ ) {
executor. submit ( ( ) - > {
SignInfo signInfo = SignInfoFactory. getSignInfo ( "科目0考试地点0" ) ;
synchronized ( signInfo) {
signInfo. setId ( "id" ) ;
try {
countDownLatch. await ( ) ;
} catch ( InterruptedException e) {
e. printStackTrace ( ) ;
}
signInfo. setLocation ( "id" ) ;
if ( ! ( signInfo. getId ( ) . equals ( signInfo. getLocation ( ) ) ) ) {
System. out. println ( signInfo) ;
}
}
} ) ;
}
for ( int j = 0 ; j < 30 ; j++ ) {
countDownLatch. countDown ( ) ;
executor. execute ( ( ) - > {
SignInfo signInfo = SignInfoFactory. getSignInfo ( "科目0考试地点0" ) ;
synchronized ( signInfo) {
signInfo. setId ( "2" ) ;
signInfo. setLocation ( "2" ) ;
if ( ! ( signInfo. getId ( ) . equals ( signInfo. getLocation ( ) ) ) ) {
System. out. println ( signInfo) ;
}
}
} ) ;
}
try {
System. in. read ( ) ;
executor. shutdownNow ( ) ;
} catch ( IOException e) {
e. printStackTrace ( ) ;
}
}
}
class CustomThredFactory implements ThreadFactory {
private final String namePrefix;
private final AtomicInteger nextId = new AtomicInteger ( 1 ) ;
CustomThredFactory ( String whatFeaturOfGroup) {
namePrefix = whatFeaturOfGroup + "-Worker-" ;
}
@Override
public Thread newThread ( Runnable task) {
String name = namePrefix + nextId. getAndIncrement ( ) ;
Thread thread = new Thread ( task, name) ;
System. out. println ( thread. getName ( ) ) ;
return thread;
}
}
class SignInfo {
private String id;
private String location;
private String subject;
private String postAddress;
public String getId ( ) {
return id;
}
public void setId ( String id) {
this . id = id;
}
public String getLocation ( ) {
return location;
}
public void setLocation ( String location) {
this . location = location;
}
public String getSubject ( ) {
return subject;
}
public void setSubject ( String subject) {
this . subject = subject;
}
public String getPostAddress ( ) {
return postAddress;
}
public void setPostAddress ( String postAddress) {
this . postAddress = postAddress;
}
@Override
public String toString ( ) {
return "SignInfo{" +
"id='" + id + '\'' +
", location='" + location + '\'' +
", subject='" + subject + '\'' +
", postAddress='" + postAddress + '\'' +
'}' ;
}
}
class SignInfo4Pool extends SignInfo {
private String key;
public SignInfo4Pool ( String _key) {
this . key = _key;
}
public String getKey ( ) {
return key;
}
public void setKey ( String key) {
this . key = key;
}
}
class SignInfoFactory {
private static HashMap< String, SignInfo> pool = new HashMap < > ( ) ;
@Deprecated
public static SignInfo SignInfo ( ) {
return new SignInfo ( ) ;
}
public static SignInfo getSignInfo ( String key) {
SignInfo result = null;
if ( ! pool. containsKey ( key) ) {
System. out. println ( key + "----建立对象,并放置到池中" ) ;
result = new SignInfo4Pool ( key) ;
pool. put ( key, result) ;
} else {
result = pool. get ( key) ;
System. out. println ( key + "---直接从池中取得" ) ;
}
return result;
}
}