import
java.math.BigInteger;
import
java.nio.charset.StandardCharsets;
import
java.security.MessageDigest;
import
java.security.NoSuchAlgorithmException;
import
java.util.concurrent.Callable;
import
java.util.concurrent.ConcurrentHashMap;
import
java.util.concurrent.ExecutionException;
import
java.util.concurrent.ExecutorService;
import
java.util.concurrent.Executors;
import
java.util.concurrent.ForkJoinPool;
import
java.util.concurrent.Future;
import
java.util.concurrent.RecursiveTask;
import
org.apache.http.client.methods.CloseableHttpResponse;
import
org.apache.http.client.methods.HttpGet;
import
org.apache.http.impl.client.CloseableHttpClient;
import
org.apache.http.impl.client.HttpClients;
import
org.apache.http.util.EntityUtils;
class
ForkJoinPoolTest {
public
static
class
FetchPage
implements
ForkJoinPool.ManagedBlocker {
private
String url;
private
ExecutorService executorSerivce;
private
byte
[] pageBytes;
private
static
ConcurrentHashMap<String,
byte
[]>
pagesMap =
new
ConcurrentHashMap<>();
public
FetchPage(String url,
ExecutorService executorSerivce)
{
this
.url = url;
this
.executorSerivce = executorSerivce;
}
@Override
public
boolean
block()
throws
InterruptedException
{
if
((pageBytes = pagesMap.get(url)) !=
null
) {
return
true
;
}
Callable<
byte
[]> callable
=
new
Callable<
byte
[]>() {
public
byte
[] call()
throws
Exception
{
CloseableHttpClient client
= HttpClients.createDefault();
HttpGet request
=
new
HttpGet(url);
CloseableHttpResponse response
= client.execute(request);
return
EntityUtils.toByteArray(
response.getEntity());
}
};
Future<
byte
[]> future
= executorSerivce.submit(callable);
try
{
pageBytes = future.get();
}
catch
(InterruptedException
| ExecutionException e) {
pageBytes =
null
;
}
return
true
;
}
@Override
public
boolean
isReleasable()
{
if
(pageBytes !=
null
) {
return
true
;
}
return
false
;
}
public
byte
[] getPage() {
return
pageBytes; }
}
static
class
MyRecursiveTask
extends
RecursiveTask<String> {
private
String url;
private
ExecutorService executorSerivce;
public
MyRecursiveTask(
String url, ExecutorService executorSerivce)
{
this
.url = url;
this
.executorSerivce = executorSerivce;
}
protected
String compute()
{
try
{
FetchPage fp
=
new
FetchPage(url, executorSerivce);
ForkJoinPool.managedBlock(fp);
byte
[] bytes = fp.getPage();
if
(bytes !=
null
) {
String code
= toHexString(getSHA(bytes));
hashPageMap.put(url, code);
return
code;
}
}
catch
(InterruptedException
| NoSuchAlgorithmException e) {
return
null
;
}
return
null
;
}
}
private
static
ConcurrentHashMap<String, String>
hashPageMap =
new
ConcurrentHashMap<>();
public
static
void
main(String[] args)
{
ExecutorService executorSerivce
= Executors.newFixedThreadPool(
50
);
ForkJoinPool forkJoinPool
= ForkJoinPool.commonPool();
MyRecursiveTask task1 =
new
MyRecursiveTask(
MyRecursiveTask task2 =
new
MyRecursiveTask(
Future<String> f1 = forkJoinPool.submit(task1);
Future<String> f2 = forkJoinPool.submit(task2);
try
{
String res1 = f1.get();
String res2 = f2.get();
System.out.println(
System.out.println(
executorSerivce.shutdown();
}
catch
(InterruptedException
| ExecutionException e) {
e.printStackTrace();
}
}
public
static
byte
[] getSHA(
byte
[] input)
throws
NoSuchAlgorithmException
{
MessageDigest md
= MessageDigest.getInstance(
"SHA-256"
);
return
md.digest(input);
}
public
static
String toHexString(
byte
[] hash)
{
BigInteger number =
new
BigInteger(
1
, hash);
StringBuilder hexString
=
new
StringBuilder(number.toString(
16
));
while
(hexString.length() <
32
) {
hexString.insert(
0
,
'0'
);
}
return
hexString.toString();
}
}