Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
openanolis
dragonwell8_jdk
提交
6693c900
D
dragonwell8_jdk
项目概览
openanolis
/
dragonwell8_jdk
通知
4
Star
2
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
D
dragonwell8_jdk
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
提交
6693c900
编写于
7月 09, 2013
作者:
V
valeriep
浏览文件
操作
浏览文件
下载
差异文件
Merge
上级
eff43a56
2a626bde
变更
38
隐藏空白更改
内联
并排
Showing
38 changed file
with
1319 addition
and
1302 deletion
+1319
-1302
src/share/classes/java/io/DataInput.java
src/share/classes/java/io/DataInput.java
+9
-9
src/share/classes/java/io/FileInputStream.java
src/share/classes/java/io/FileInputStream.java
+1
-1
src/share/classes/java/io/FileOutputStream.java
src/share/classes/java/io/FileOutputStream.java
+2
-2
src/share/classes/java/io/InputStreamReader.java
src/share/classes/java/io/InputStreamReader.java
+4
-4
src/share/classes/java/io/OutputStreamWriter.java
src/share/classes/java/io/OutputStreamWriter.java
+5
-5
src/share/classes/java/io/PipedInputStream.java
src/share/classes/java/io/PipedInputStream.java
+7
-7
src/share/classes/java/io/RandomAccessFile.java
src/share/classes/java/io/RandomAccessFile.java
+6
-6
src/share/classes/java/util/LinkedList.java
src/share/classes/java/util/LinkedList.java
+1
-6
src/share/classes/java/util/Spliterators.java
src/share/classes/java/util/Spliterators.java
+8
-48
src/share/classes/java/util/concurrent/AbstractExecutorService.java
...classes/java/util/concurrent/AbstractExecutorService.java
+34
-32
src/share/classes/java/util/concurrent/Callable.java
src/share/classes/java/util/concurrent/Callable.java
+6
-6
src/share/classes/java/util/concurrent/CancellationException.java
...e/classes/java/util/concurrent/CancellationException.java
+2
-2
src/share/classes/java/util/concurrent/CompletableFuture.java
...share/classes/java/util/concurrent/CompletableFuture.java
+2
-2
src/share/classes/java/util/concurrent/CompletionService.java
...share/classes/java/util/concurrent/CompletionService.java
+12
-12
src/share/classes/java/util/concurrent/CountedCompleter.java
src/share/classes/java/util/concurrent/CountedCompleter.java
+86
-62
src/share/classes/java/util/concurrent/ExecutionException.java
...hare/classes/java/util/concurrent/ExecutionException.java
+4
-4
src/share/classes/java/util/concurrent/Executor.java
src/share/classes/java/util/concurrent/Executor.java
+7
-7
src/share/classes/java/util/concurrent/ExecutorService.java
src/share/classes/java/util/concurrent/ExecutorService.java
+38
-38
src/share/classes/java/util/concurrent/Executors.java
src/share/classes/java/util/concurrent/Executors.java
+86
-50
src/share/classes/java/util/concurrent/ForkJoinPool.java
src/share/classes/java/util/concurrent/ForkJoinPool.java
+549
-647
src/share/classes/java/util/concurrent/ForkJoinTask.java
src/share/classes/java/util/concurrent/ForkJoinTask.java
+46
-32
src/share/classes/java/util/concurrent/ForkJoinWorkerThread.java
...re/classes/java/util/concurrent/ForkJoinWorkerThread.java
+9
-8
src/share/classes/java/util/concurrent/Future.java
src/share/classes/java/util/concurrent/Future.java
+21
-21
src/share/classes/java/util/concurrent/FutureTask.java
src/share/classes/java/util/concurrent/FutureTask.java
+16
-12
src/share/classes/java/util/concurrent/RecursiveAction.java
src/share/classes/java/util/concurrent/RecursiveAction.java
+12
-12
src/share/classes/java/util/concurrent/RecursiveTask.java
src/share/classes/java/util/concurrent/RecursiveTask.java
+2
-1
src/share/classes/java/util/concurrent/RejectedExecutionException.java
...sses/java/util/concurrent/RejectedExecutionException.java
+5
-5
src/share/classes/java/util/concurrent/RunnableFuture.java
src/share/classes/java/util/concurrent/RunnableFuture.java
+2
-2
src/share/classes/java/util/concurrent/RunnableScheduledFuture.java
...classes/java/util/concurrent/RunnableScheduledFuture.java
+5
-5
src/share/classes/java/util/concurrent/ScheduledExecutorService.java
...lasses/java/util/concurrent/ScheduledExecutorService.java
+18
-18
src/share/classes/java/util/concurrent/ScheduledThreadPoolExecutor.java
...ses/java/util/concurrent/ScheduledThreadPoolExecutor.java
+9
-7
src/share/classes/java/util/concurrent/ThreadPoolExecutor.java
...hare/classes/java/util/concurrent/ThreadPoolExecutor.java
+81
-85
src/share/classes/java/util/regex/MatchResult.java
src/share/classes/java/util/regex/MatchResult.java
+2
-2
src/share/classes/java/util/regex/Matcher.java
src/share/classes/java/util/regex/Matcher.java
+8
-7
src/share/classes/java/util/regex/Pattern.java
src/share/classes/java/util/regex/Pattern.java
+92
-100
src/share/classes/java/util/stream/AbstractPipeline.java
src/share/classes/java/util/stream/AbstractPipeline.java
+5
-18
src/share/classes/java/util/stream/BaseStream.java
src/share/classes/java/util/stream/BaseStream.java
+2
-4
test/java/lang/SecurityManager/CheckPackageAccess.java
test/java/lang/SecurityManager/CheckPackageAccess.java
+115
-13
未找到文件。
src/share/classes/java/io/DataInput.java
浏览文件 @
6693c900
/*
/*
* Copyright (c) 1995, 201
2
, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1995, 201
3
, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
*
* This code is free software; you can redistribute it and/or modify it
* This code is free software; you can redistribute it and/or modify it
...
@@ -66,10 +66,10 @@ package java.io;
...
@@ -66,10 +66,10 @@ package java.io;
* summary="Bit values and bytes">
* summary="Bit values and bytes">
* <tr>
* <tr>
* <td></td>
* <td></td>
* <th id="bit">Bit Values</th>
* <th id="bit
_a
">Bit Values</th>
* </tr>
* </tr>
* <tr>
* <tr>
* <th id="byte1">Byte 1</th>
* <th id="byte1
_a
">Byte 1</th>
* <td>
* <td>
* <table border="1" cellspacing="0" width="100%">
* <table border="1" cellspacing="0" width="100%">
* <tr>
* <tr>
...
@@ -92,10 +92,10 @@ package java.io;
...
@@ -92,10 +92,10 @@ package java.io;
* summary="Bit values and bytes">
* summary="Bit values and bytes">
* <tr>
* <tr>
* <td></td>
* <td></td>
* <th id="bit">Bit Values</th>
* <th id="bit
_b
">Bit Values</th>
* </tr>
* </tr>
* <tr>
* <tr>
* <th id="byte1">Byte 1</th>
* <th id="byte1
_b
">Byte 1</th>
* <td>
* <td>
* <table border="1" cellspacing="0" width="100%">
* <table border="1" cellspacing="0" width="100%">
* <tr>
* <tr>
...
@@ -108,7 +108,7 @@ package java.io;
...
@@ -108,7 +108,7 @@ package java.io;
* </td>
* </td>
* </tr>
* </tr>
* <tr>
* <tr>
* <th id="byte2">Byte 2</th>
* <th id="byte2
_a
">Byte 2</th>
* <td>
* <td>
* <table border="1" cellspacing="0" width="100%">
* <table border="1" cellspacing="0" width="100%">
* <tr>
* <tr>
...
@@ -131,10 +131,10 @@ package java.io;
...
@@ -131,10 +131,10 @@ package java.io;
* summary="Bit values and bytes">
* summary="Bit values and bytes">
* <tr>
* <tr>
* <td></td>
* <td></td>
* <th id="bit">Bit Values</th>
* <th id="bit
_c
">Bit Values</th>
* </tr>
* </tr>
* <tr>
* <tr>
* <th id="byte1">Byte 1</th>
* <th id="byte1
_c
">Byte 1</th>
* <td>
* <td>
* <table border="1" cellspacing="0" width="100%">
* <table border="1" cellspacing="0" width="100%">
* <tr>
* <tr>
...
@@ -148,7 +148,7 @@ package java.io;
...
@@ -148,7 +148,7 @@ package java.io;
* </td>
* </td>
* </tr>
* </tr>
* <tr>
* <tr>
* <th id="byte2">Byte 2</th>
* <th id="byte2
_b
">Byte 2</th>
* <td>
* <td>
* <table border="1" cellspacing="0" width="100%">
* <table border="1" cellspacing="0" width="100%">
* <tr>
* <tr>
...
...
src/share/classes/java/io/FileInputStream.java
浏览文件 @
6693c900
...
@@ -331,7 +331,7 @@ class FileInputStream extends InputStream
...
@@ -331,7 +331,7 @@ class FileInputStream extends InputStream
* object associated with this file input stream.
* object associated with this file input stream.
*
*
* <p> The initial {@link java.nio.channels.FileChannel#position()
* <p> The initial {@link java.nio.channels.FileChannel#position()
*
</code>position<code>
} of the returned channel will be equal to the
*
position
} of the returned channel will be equal to the
* number of bytes read from the file so far. Reading bytes from this
* number of bytes read from the file so far. Reading bytes from this
* stream will increment the channel's position. Changing the channel's
* stream will increment the channel's position. Changing the channel's
* position, either explicitly or by reading, will change this stream's
* position, either explicitly or by reading, will change this stream's
...
...
src/share/classes/java/io/FileOutputStream.java
浏览文件 @
6693c900
...
@@ -358,10 +358,10 @@ class FileOutputStream extends OutputStream
...
@@ -358,10 +358,10 @@ class FileOutputStream extends OutputStream
/**
/**
* Returns the unique {@link java.nio.channels.FileChannel FileChannel}
* Returns the unique {@link java.nio.channels.FileChannel FileChannel}
* object associated with this file output stream.
</p>
* object associated with this file output stream.
*
*
* <p> The initial {@link java.nio.channels.FileChannel#position()
* <p> The initial {@link java.nio.channels.FileChannel#position()
*
</code>position<code>
} of the returned channel will be equal to the
*
position
} of the returned channel will be equal to the
* number of bytes written to the file so far unless this stream is in
* number of bytes written to the file so far unless this stream is in
* append mode, in which case it will be equal to the size of the file.
* append mode, in which case it will be equal to the size of the file.
* Writing bytes to this stream will increment the channel's position
* Writing bytes to this stream will increment the channel's position
...
...
src/share/classes/java/io/InputStreamReader.java
浏览文件 @
6693c900
/*
/*
* Copyright (c) 1996, 201
2
, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1996, 201
3
, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
*
* This code is free software; you can redistribute it and/or modify it
* This code is free software; you can redistribute it and/or modify it
...
@@ -33,7 +33,7 @@ import sun.nio.cs.StreamDecoder;
...
@@ -33,7 +33,7 @@ import sun.nio.cs.StreamDecoder;
/**
/**
* An InputStreamReader is a bridge from byte streams to character streams: It
* An InputStreamReader is a bridge from byte streams to character streams: It
* reads bytes and decodes them into characters using a specified {@link
* reads bytes and decodes them into characters using a specified {@link
* java.nio.charset.Charset
<code>charset</code>
}. The charset that it uses
* java.nio.charset.Charset
charset
}. The charset that it uses
* may be specified by name or may be given explicitly, or the platform's
* may be specified by name or may be given explicitly, or the platform's
* default charset may be accepted.
* default charset may be accepted.
*
*
...
@@ -101,7 +101,7 @@ public class InputStreamReader extends Reader {
...
@@ -101,7 +101,7 @@ public class InputStreamReader extends Reader {
}
}
/**
/**
* Creates an InputStreamReader that uses the given charset.
</p>
* Creates an InputStreamReader that uses the given charset.
*
*
* @param in An InputStream
* @param in An InputStream
* @param cs A charset
* @param cs A charset
...
@@ -117,7 +117,7 @@ public class InputStreamReader extends Reader {
...
@@ -117,7 +117,7 @@ public class InputStreamReader extends Reader {
}
}
/**
/**
* Creates an InputStreamReader that uses the given charset decoder.
</p>
* Creates an InputStreamReader that uses the given charset decoder.
*
*
* @param in An InputStream
* @param in An InputStream
* @param dec A charset decoder
* @param dec A charset decoder
...
...
src/share/classes/java/io/OutputStreamWriter.java
浏览文件 @
6693c900
/*
/*
* Copyright (c) 1996, 20
06
, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1996, 20
13
, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
*
* This code is free software; you can redistribute it and/or modify it
* This code is free software; you can redistribute it and/or modify it
...
@@ -33,7 +33,7 @@ import sun.nio.cs.StreamEncoder;
...
@@ -33,7 +33,7 @@ import sun.nio.cs.StreamEncoder;
/**
/**
* An OutputStreamWriter is a bridge from character streams to byte streams:
* An OutputStreamWriter is a bridge from character streams to byte streams:
* Characters written to it are encoded into bytes using a specified {@link
* Characters written to it are encoded into bytes using a specified {@link
* java.nio.charset.Charset
<code>charset</code>
}. The charset that it uses
* java.nio.charset.Charset
charset
}. The charset that it uses
* may be specified by name or may be given explicitly, or the platform's
* may be specified by name or may be given explicitly, or the platform's
* default charset may be accepted.
* default charset may be accepted.
*
*
...
@@ -86,7 +86,7 @@ public class OutputStreamWriter extends Writer {
...
@@ -86,7 +86,7 @@ public class OutputStreamWriter extends Writer {
*
*
* @param charsetName
* @param charsetName
* The name of a supported
* The name of a supported
* {@link java.nio.charset.Charset
</code>charset<code>
}
* {@link java.nio.charset.Charset
charset
}
*
*
* @exception UnsupportedEncodingException
* @exception UnsupportedEncodingException
* If the named encoding is not supported
* If the named encoding is not supported
...
@@ -115,7 +115,7 @@ public class OutputStreamWriter extends Writer {
...
@@ -115,7 +115,7 @@ public class OutputStreamWriter extends Writer {
}
}
/**
/**
* Creates an OutputStreamWriter that uses the given charset.
</p>
* Creates an OutputStreamWriter that uses the given charset.
*
*
* @param out
* @param out
* An OutputStream
* An OutputStream
...
@@ -134,7 +134,7 @@ public class OutputStreamWriter extends Writer {
...
@@ -134,7 +134,7 @@ public class OutputStreamWriter extends Writer {
}
}
/**
/**
* Creates an OutputStreamWriter that uses the given charset encoder.
</p>
* Creates an OutputStreamWriter that uses the given charset encoder.
*
*
* @param out
* @param out
* An OutputStream
* An OutputStream
...
...
src/share/classes/java/io/PipedInputStream.java
浏览文件 @
6693c900
/*
/*
* Copyright (c) 1995, 20
06
, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1995, 20
13
, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
*
* This code is free software; you can redistribute it and/or modify it
* This code is free software; you can redistribute it and/or modify it
...
@@ -39,7 +39,7 @@ package java.io;
...
@@ -39,7 +39,7 @@ package java.io;
* The piped input stream contains a buffer,
* The piped input stream contains a buffer,
* decoupling read operations from write operations,
* decoupling read operations from write operations,
* within limits.
* within limits.
* A pipe is said to be <a name=
BROKEN
> <i>broken</i> </a> if a
* A pipe is said to be <a name=
"BROKEN"
> <i>broken</i> </a> if a
* thread that was providing data bytes to the connected
* thread that was providing data bytes to the connected
* piped output stream is no longer alive.
* piped output stream is no longer alive.
*
*
...
@@ -193,7 +193,7 @@ public class PipedInputStream extends InputStream {
...
@@ -193,7 +193,7 @@ public class PipedInputStream extends InputStream {
* Receives a byte of data. This method will block if no input is
* Receives a byte of data. This method will block if no input is
* available.
* available.
* @param b the byte being received
* @param b the byte being received
* @exception IOException If the pipe is <a href=
#BROKEN
> <code>broken</code></a>,
* @exception IOException If the pipe is <a href=
"#BROKEN"
> <code>broken</code></a>,
* {@link #connect(java.io.PipedOutputStream) unconnected},
* {@link #connect(java.io.PipedOutputStream) unconnected},
* closed, or if an I/O error occurs.
* closed, or if an I/O error occurs.
* @since JDK1.1
* @since JDK1.1
...
@@ -219,7 +219,7 @@ public class PipedInputStream extends InputStream {
...
@@ -219,7 +219,7 @@ public class PipedInputStream extends InputStream {
* @param b the buffer into which the data is received
* @param b the buffer into which the data is received
* @param off the start offset of the data
* @param off the start offset of the data
* @param len the maximum number of bytes received
* @param len the maximum number of bytes received
* @exception IOException If the pipe is <a href=
#BROKEN
> broken</a>,
* @exception IOException If the pipe is <a href=
"#BROKEN"
> broken</a>,
* {@link #connect(java.io.PipedOutputStream) unconnected},
* {@link #connect(java.io.PipedOutputStream) unconnected},
* closed,or if an I/O error occurs.
* closed,or if an I/O error occurs.
*/
*/
...
@@ -298,7 +298,7 @@ public class PipedInputStream extends InputStream {
...
@@ -298,7 +298,7 @@ public class PipedInputStream extends InputStream {
* stream is reached.
* stream is reached.
* @exception IOException if the pipe is
* @exception IOException if the pipe is
* {@link #connect(java.io.PipedOutputStream) unconnected},
* {@link #connect(java.io.PipedOutputStream) unconnected},
* <a href=
#BROKEN
> <code>broken</code></a>, closed,
* <a href=
"#BROKEN"
> <code>broken</code></a>, closed,
* or if an I/O error occurs.
* or if an I/O error occurs.
*/
*/
public
synchronized
int
read
()
throws
IOException
{
public
synchronized
int
read
()
throws
IOException
{
...
@@ -361,7 +361,7 @@ public class PipedInputStream extends InputStream {
...
@@ -361,7 +361,7 @@ public class PipedInputStream extends InputStream {
* @exception IndexOutOfBoundsException If <code>off</code> is negative,
* @exception IndexOutOfBoundsException If <code>off</code> is negative,
* <code>len</code> is negative, or <code>len</code> is greater than
* <code>len</code> is negative, or <code>len</code> is greater than
* <code>b.length - off</code>
* <code>b.length - off</code>
* @exception IOException if the pipe is <a href=
#BROKEN
> <code>broken</code></a>,
* @exception IOException if the pipe is <a href=
"#BROKEN"
> <code>broken</code></a>,
* {@link #connect(java.io.PipedOutputStream) unconnected},
* {@link #connect(java.io.PipedOutputStream) unconnected},
* closed, or if an I/O error occurs.
* closed, or if an I/O error occurs.
*/
*/
...
@@ -419,7 +419,7 @@ public class PipedInputStream extends InputStream {
...
@@ -419,7 +419,7 @@ public class PipedInputStream extends InputStream {
* without blocking, or {@code 0} if this input stream has been
* without blocking, or {@code 0} if this input stream has been
* closed by invoking its {@link #close()} method, or if the pipe
* closed by invoking its {@link #close()} method, or if the pipe
* is {@link #connect(java.io.PipedOutputStream) unconnected}, or
* is {@link #connect(java.io.PipedOutputStream) unconnected}, or
* <a href=
#BROKEN
> <code>broken</code></a>.
* <a href=
"#BROKEN"
> <code>broken</code></a>.
*
*
* @exception IOException if an I/O error occurs.
* @exception IOException if an I/O error occurs.
* @since JDK1.0.2
* @since JDK1.0.2
...
...
src/share/classes/java/io/RandomAccessFile.java
浏览文件 @
6693c900
...
@@ -123,11 +123,11 @@ public class RandomAccessFile implements DataOutput, DataInput, Closeable {
...
@@ -123,11 +123,11 @@ public class RandomAccessFile implements DataOutput, DataInput, Closeable {
* write to, the file specified by the {@link File} argument. A new {@link
* write to, the file specified by the {@link File} argument. A new {@link
* FileDescriptor} object is created to represent this file connection.
* FileDescriptor} object is created to represent this file connection.
*
*
* <
a name="mode"><p> The <tt>mode</tt
> argument specifies the access mode
* <
p>The <a name="mode"><tt>mode</tt></a
> argument specifies the access mode
* in which the file is to be opened. The permitted values and their
* in which the file is to be opened. The permitted values and their
* meanings are:
* meanings are:
*
*
* <
blockquote><
table summary="Access mode permitted values and meanings">
* <table summary="Access mode permitted values and meanings">
* <tr><th><p align="left">Value</p></th><th><p align="left">Meaning</p></th></tr>
* <tr><th><p align="left">Value</p></th><th><p align="left">Meaning</p></th></tr>
* <tr><td valign="top"><tt>"r"</tt></td>
* <tr><td valign="top"><tt>"r"</tt></td>
* <td> Open for reading only. Invoking any of the <tt>write</tt>
* <td> Open for reading only. Invoking any of the <tt>write</tt>
...
@@ -144,7 +144,7 @@ public class RandomAccessFile implements DataOutput, DataInput, Closeable {
...
@@ -144,7 +144,7 @@ public class RandomAccessFile implements DataOutput, DataInput, Closeable {
* <td> Open for reading and writing, as with <tt>"rw"</tt>, and also
* <td> Open for reading and writing, as with <tt>"rw"</tt>, and also
* require that every update to the file's content be written
* require that every update to the file's content be written
* synchronously to the underlying storage device. </td></tr>
* synchronously to the underlying storage device. </td></tr>
* </table>
</blockquote>
* </table>
*
*
* The <tt>"rws"</tt> and <tt>"rwd"</tt> modes work much like the {@link
* The <tt>"rws"</tt> and <tt>"rwd"</tt> modes work much like the {@link
* java.nio.channels.FileChannel#force(boolean) force(boolean)} method of
* java.nio.channels.FileChannel#force(boolean) force(boolean)} method of
...
@@ -158,13 +158,13 @@ public class RandomAccessFile implements DataOutput, DataInput, Closeable {
...
@@ -158,13 +158,13 @@ public class RandomAccessFile implements DataOutput, DataInput, Closeable {
* event of a system crash. If the file does not reside on a local device
* event of a system crash. If the file does not reside on a local device
* then no such guarantee is made.
* then no such guarantee is made.
*
*
* <p>
The <tt>"rwd"</tt> mode can be used to reduce the number of I/O
* <p>The <tt>"rwd"</tt> mode can be used to reduce the number of I/O
* operations performed. Using <tt>"rwd"</tt> only requires updates to the
* operations performed. Using <tt>"rwd"</tt> only requires updates to the
* file's content to be written to storage; using <tt>"rws"</tt> requires
* file's content to be written to storage; using <tt>"rws"</tt> requires
* updates to both the file's content and its metadata to be written, which
* updates to both the file's content and its metadata to be written, which
* generally requires at least one more low-level I/O operation.
* generally requires at least one more low-level I/O operation.
*
*
* <p>
If there is a security manager, its {@code checkRead} method is
* <p>If there is a security manager, its {@code checkRead} method is
* called with the pathname of the {@code file} argument as its
* called with the pathname of the {@code file} argument as its
* argument to see if read access to the file is allowed. If the mode
* argument to see if read access to the file is allowed. If the mode
* allows writing, the security manager's {@code checkWrite} method is
* allows writing, the security manager's {@code checkWrite} method is
...
@@ -238,7 +238,7 @@ public class RandomAccessFile implements DataOutput, DataInput, Closeable {
...
@@ -238,7 +238,7 @@ public class RandomAccessFile implements DataOutput, DataInput, Closeable {
/**
/**
* Returns the opaque file descriptor object associated with this
* Returns the opaque file descriptor object associated with this
* stream.
</p>
* stream.
*
*
* @return the file descriptor object associated with this stream.
* @return the file descriptor object associated with this stream.
* @exception IOException if an I/O error occurs.
* @exception IOException if an I/O error occurs.
...
...
src/share/classes/java/util/LinkedList.java
浏览文件 @
6693c900
...
@@ -1195,12 +1195,7 @@ public class LinkedList<E>
...
@@ -1195,12 +1195,7 @@ public class LinkedList<E>
n
=
s
;
n
=
s
;
if
(
n
>
MAX_BATCH
)
if
(
n
>
MAX_BATCH
)
n
=
MAX_BATCH
;
n
=
MAX_BATCH
;
Object
[]
a
;
Object
[]
a
=
new
Object
[
n
];
try
{
a
=
new
Object
[
n
];
}
catch
(
OutOfMemoryError
oome
)
{
return
null
;
}
int
j
=
0
;
int
j
=
0
;
do
{
a
[
j
++]
=
p
.
item
;
}
while
((
p
=
p
.
next
)
!=
null
&&
j
<
n
);
do
{
a
[
j
++]
=
p
.
item
;
}
while
((
p
=
p
.
next
)
!=
null
&&
j
<
n
);
current
=
p
;
current
=
p
;
...
...
src/share/classes/java/util/Spliterators.java
浏览文件 @
6693c900
...
@@ -1314,12 +1314,7 @@ public final class Spliterators {
...
@@ -1314,12 +1314,7 @@ public final class Spliterators {
n
=
(
int
)
s
;
n
=
(
int
)
s
;
if
(
n
>
MAX_BATCH
)
if
(
n
>
MAX_BATCH
)
n
=
MAX_BATCH
;
n
=
MAX_BATCH
;
Object
[]
a
;
Object
[]
a
=
new
Object
[
n
];
try
{
a
=
new
Object
[
n
];
}
catch
(
OutOfMemoryError
oome
)
{
return
null
;
}
int
j
=
0
;
int
j
=
0
;
do
{
a
[
j
]
=
holder
.
value
;
}
while
(++
j
<
n
&&
tryAdvance
(
holder
));
do
{
a
[
j
]
=
holder
.
value
;
}
while
(++
j
<
n
&&
tryAdvance
(
holder
));
batch
=
j
;
batch
=
j
;
...
@@ -1429,12 +1424,7 @@ public final class Spliterators {
...
@@ -1429,12 +1424,7 @@ public final class Spliterators {
n
=
(
int
)
s
;
n
=
(
int
)
s
;
if
(
n
>
MAX_BATCH
)
if
(
n
>
MAX_BATCH
)
n
=
MAX_BATCH
;
n
=
MAX_BATCH
;
int
[]
a
;
int
[]
a
=
new
int
[
n
];
try
{
a
=
new
int
[
n
];
}
catch
(
OutOfMemoryError
oome
)
{
return
null
;
}
int
j
=
0
;
int
j
=
0
;
do
{
a
[
j
]
=
holder
.
value
;
}
while
(++
j
<
n
&&
tryAdvance
(
holder
));
do
{
a
[
j
]
=
holder
.
value
;
}
while
(++
j
<
n
&&
tryAdvance
(
holder
));
batch
=
j
;
batch
=
j
;
...
@@ -1544,12 +1534,7 @@ public final class Spliterators {
...
@@ -1544,12 +1534,7 @@ public final class Spliterators {
n
=
(
int
)
s
;
n
=
(
int
)
s
;
if
(
n
>
MAX_BATCH
)
if
(
n
>
MAX_BATCH
)
n
=
MAX_BATCH
;
n
=
MAX_BATCH
;
long
[]
a
;
long
[]
a
=
new
long
[
n
];
try
{
a
=
new
long
[
n
];
}
catch
(
OutOfMemoryError
oome
)
{
return
null
;
}
int
j
=
0
;
int
j
=
0
;
do
{
a
[
j
]
=
holder
.
value
;
}
while
(++
j
<
n
&&
tryAdvance
(
holder
));
do
{
a
[
j
]
=
holder
.
value
;
}
while
(++
j
<
n
&&
tryAdvance
(
holder
));
batch
=
j
;
batch
=
j
;
...
@@ -1659,12 +1644,7 @@ public final class Spliterators {
...
@@ -1659,12 +1644,7 @@ public final class Spliterators {
n
=
(
int
)
s
;
n
=
(
int
)
s
;
if
(
n
>
MAX_BATCH
)
if
(
n
>
MAX_BATCH
)
n
=
MAX_BATCH
;
n
=
MAX_BATCH
;
double
[]
a
;
double
[]
a
=
new
double
[
n
];
try
{
a
=
new
double
[
n
];
}
catch
(
OutOfMemoryError
oome
)
{
return
null
;
}
int
j
=
0
;
int
j
=
0
;
do
{
a
[
j
]
=
holder
.
value
;
}
while
(++
j
<
n
&&
tryAdvance
(
holder
));
do
{
a
[
j
]
=
holder
.
value
;
}
while
(++
j
<
n
&&
tryAdvance
(
holder
));
batch
=
j
;
batch
=
j
;
...
@@ -1795,12 +1775,7 @@ public final class Spliterators {
...
@@ -1795,12 +1775,7 @@ public final class Spliterators {
n
=
(
int
)
s
;
n
=
(
int
)
s
;
if
(
n
>
MAX_BATCH
)
if
(
n
>
MAX_BATCH
)
n
=
MAX_BATCH
;
n
=
MAX_BATCH
;
Object
[]
a
;
Object
[]
a
=
new
Object
[
n
];
try
{
a
=
new
Object
[
n
];
}
catch
(
OutOfMemoryError
oome
)
{
return
null
;
}
int
j
=
0
;
int
j
=
0
;
do
{
a
[
j
]
=
i
.
next
();
}
while
(++
j
<
n
&&
i
.
hasNext
());
do
{
a
[
j
]
=
i
.
next
();
}
while
(++
j
<
n
&&
i
.
hasNext
());
batch
=
j
;
batch
=
j
;
...
@@ -1910,12 +1885,7 @@ public final class Spliterators {
...
@@ -1910,12 +1885,7 @@ public final class Spliterators {
n
=
(
int
)
s
;
n
=
(
int
)
s
;
if
(
n
>
MAX_BATCH
)
if
(
n
>
MAX_BATCH
)
n
=
MAX_BATCH
;
n
=
MAX_BATCH
;
int
[]
a
;
int
[]
a
=
new
int
[
n
];
try
{
a
=
new
int
[
n
];
}
catch
(
OutOfMemoryError
oome
)
{
return
null
;
}
int
j
=
0
;
int
j
=
0
;
do
{
a
[
j
]
=
i
.
nextInt
();
}
while
(++
j
<
n
&&
i
.
hasNext
());
do
{
a
[
j
]
=
i
.
nextInt
();
}
while
(++
j
<
n
&&
i
.
hasNext
());
batch
=
j
;
batch
=
j
;
...
@@ -2007,12 +1977,7 @@ public final class Spliterators {
...
@@ -2007,12 +1977,7 @@ public final class Spliterators {
n
=
(
int
)
s
;
n
=
(
int
)
s
;
if
(
n
>
MAX_BATCH
)
if
(
n
>
MAX_BATCH
)
n
=
MAX_BATCH
;
n
=
MAX_BATCH
;
long
[]
a
;
long
[]
a
=
new
long
[
n
];
try
{
a
=
new
long
[
n
];
}
catch
(
OutOfMemoryError
oome
)
{
return
null
;
}
int
j
=
0
;
int
j
=
0
;
do
{
a
[
j
]
=
i
.
nextLong
();
}
while
(++
j
<
n
&&
i
.
hasNext
());
do
{
a
[
j
]
=
i
.
nextLong
();
}
while
(++
j
<
n
&&
i
.
hasNext
());
batch
=
j
;
batch
=
j
;
...
@@ -2104,12 +2069,7 @@ public final class Spliterators {
...
@@ -2104,12 +2069,7 @@ public final class Spliterators {
n
=
(
int
)
s
;
n
=
(
int
)
s
;
if
(
n
>
MAX_BATCH
)
if
(
n
>
MAX_BATCH
)
n
=
MAX_BATCH
;
n
=
MAX_BATCH
;
double
[]
a
;
double
[]
a
=
new
double
[
n
];
try
{
a
=
new
double
[
n
];
}
catch
(
OutOfMemoryError
oome
)
{
return
null
;
}
int
j
=
0
;
int
j
=
0
;
do
{
a
[
j
]
=
i
.
nextDouble
();
}
while
(++
j
<
n
&&
i
.
hasNext
());
do
{
a
[
j
]
=
i
.
nextDouble
();
}
while
(++
j
<
n
&&
i
.
hasNext
());
batch
=
j
;
batch
=
j
;
...
...
src/share/classes/java/util/concurrent/AbstractExecutorService.java
浏览文件 @
6693c900
...
@@ -38,19 +38,19 @@ import java.util.*;
...
@@ -38,19 +38,19 @@ import java.util.*;
/**
/**
* Provides default implementations of {@link ExecutorService}
* Provides default implementations of {@link ExecutorService}
* execution methods. This class implements the
<tt>submit</tt>
,
* execution methods. This class implements the
{@code submit}
,
*
<tt>invokeAny</tt> and <tt>invokeAll</tt>
methods using a
*
{@code invokeAny} and {@code invokeAll}
methods using a
* {@link RunnableFuture} returned by
<tt>newTaskFor</tt>
, which defaults
* {@link RunnableFuture} returned by
{@code newTaskFor}
, which defaults
* to the {@link FutureTask} class provided in this package. For example,
* to the {@link FutureTask} class provided in this package. For example,
* the implementation of
<tt>submit(Runnable)</tt>
creates an
* the implementation of
{@code submit(Runnable)}
creates an
* associated
<tt>RunnableFuture</tt>
that is executed and
* associated
{@code RunnableFuture}
that is executed and
* returned. Subclasses may override the
<tt>newTaskFor</tt>
methods
* returned. Subclasses may override the
{@code newTaskFor}
methods
* to return
<tt>RunnableFuture</tt>
implementations other than
* to return
{@code RunnableFuture}
implementations other than
*
<tt>FutureTask</tt>
.
*
{@code FutureTask}
.
*
*
* <p>
<b>Extension example</b>. Here is a sketch of a class
* <p><b>Extension example</b>. Here is a sketch of a class
* that customizes {@link ThreadPoolExecutor} to use
* that customizes {@link ThreadPoolExecutor} to use
* a
<tt>CustomTask</tt> class instead of the default <tt>FutureTask</tt>
:
* a
{@code CustomTask} class instead of the default {@code FutureTask}
:
* <pre> {@code
* <pre> {@code
* public class CustomThreadPoolExecutor extends ThreadPoolExecutor {
* public class CustomThreadPoolExecutor extends ThreadPoolExecutor {
*
*
...
@@ -71,15 +71,15 @@ import java.util.*;
...
@@ -71,15 +71,15 @@ import java.util.*;
public
abstract
class
AbstractExecutorService
implements
ExecutorService
{
public
abstract
class
AbstractExecutorService
implements
ExecutorService
{
/**
/**
* Returns a
<tt>RunnableFuture</tt>
for the given runnable and default
* Returns a
{@code RunnableFuture}
for the given runnable and default
* value.
* value.
*
*
* @param runnable the runnable task being wrapped
* @param runnable the runnable task being wrapped
* @param value the default value for the returned future
* @param value the default value for the returned future
* @return a
<tt>RunnableFuture</tt> which when run
will run the
* @return a
{@code RunnableFuture} which, when run,
will run the
* underlying runnable and which, as a
<tt>Future</tt>
, will yield
* underlying runnable and which, as a
{@code Future}
, will yield
* the given value as its result and provide for cancellation of
* the given value as its result and provide for cancellation of
* the underlying task
.
* the underlying task
* @since 1.6
* @since 1.6
*/
*/
protected
<
T
>
RunnableFuture
<
T
>
newTaskFor
(
Runnable
runnable
,
T
value
)
{
protected
<
T
>
RunnableFuture
<
T
>
newTaskFor
(
Runnable
runnable
,
T
value
)
{
...
@@ -87,13 +87,13 @@ public abstract class AbstractExecutorService implements ExecutorService {
...
@@ -87,13 +87,13 @@ public abstract class AbstractExecutorService implements ExecutorService {
}
}
/**
/**
* Returns a
<tt>RunnableFuture</tt>
for the given callable task.
* Returns a
{@code RunnableFuture}
for the given callable task.
*
*
* @param callable the callable task being wrapped
* @param callable the callable task being wrapped
* @return a
<tt>RunnableFuture</tt> which when run
will call the
* @return a
{@code RunnableFuture} which, when run,
will call the
* underlying callable and which, as a
<tt>Future</tt>
, will yield
* underlying callable and which, as a
{@code Future}
, will yield
* the callable's result as its result and provide for
* the callable's result as its result and provide for
* cancellation of the underlying task
.
* cancellation of the underlying task
* @since 1.6
* @since 1.6
*/
*/
protected
<
T
>
RunnableFuture
<
T
>
newTaskFor
(
Callable
<
T
>
callable
)
{
protected
<
T
>
RunnableFuture
<
T
>
newTaskFor
(
Callable
<
T
>
callable
)
{
...
@@ -144,7 +144,7 @@ public abstract class AbstractExecutorService implements ExecutorService {
...
@@ -144,7 +144,7 @@ public abstract class AbstractExecutorService implements ExecutorService {
int
ntasks
=
tasks
.
size
();
int
ntasks
=
tasks
.
size
();
if
(
ntasks
==
0
)
if
(
ntasks
==
0
)
throw
new
IllegalArgumentException
();
throw
new
IllegalArgumentException
();
List
<
Future
<
T
>>
futures
=
new
ArrayList
<
Future
<
T
>>(
ntasks
);
ArrayList
<
Future
<
T
>>
futures
=
new
ArrayList
<
Future
<
T
>>(
ntasks
);
ExecutorCompletionService
<
T
>
ecs
=
ExecutorCompletionService
<
T
>
ecs
=
new
ExecutorCompletionService
<
T
>(
this
);
new
ExecutorCompletionService
<
T
>(
this
);
...
@@ -202,8 +202,8 @@ public abstract class AbstractExecutorService implements ExecutorService {
...
@@ -202,8 +202,8 @@ public abstract class AbstractExecutorService implements ExecutorService {
throw
ee
;
throw
ee
;
}
finally
{
}
finally
{
for
(
Future
<
T
>
f
:
futures
)
for
(
int
i
=
0
,
size
=
futures
.
size
();
i
<
size
;
i
++
)
f
.
cancel
(
true
);
f
utures
.
get
(
i
)
.
cancel
(
true
);
}
}
}
}
...
@@ -227,7 +227,7 @@ public abstract class AbstractExecutorService implements ExecutorService {
...
@@ -227,7 +227,7 @@ public abstract class AbstractExecutorService implements ExecutorService {
throws
InterruptedException
{
throws
InterruptedException
{
if
(
tasks
==
null
)
if
(
tasks
==
null
)
throw
new
NullPointerException
();
throw
new
NullPointerException
();
List
<
Future
<
T
>>
futures
=
new
ArrayList
<
Future
<
T
>>(
tasks
.
size
());
Array
List
<
Future
<
T
>>
futures
=
new
ArrayList
<
Future
<
T
>>(
tasks
.
size
());
boolean
done
=
false
;
boolean
done
=
false
;
try
{
try
{
for
(
Callable
<
T
>
t
:
tasks
)
{
for
(
Callable
<
T
>
t
:
tasks
)
{
...
@@ -235,7 +235,8 @@ public abstract class AbstractExecutorService implements ExecutorService {
...
@@ -235,7 +235,8 @@ public abstract class AbstractExecutorService implements ExecutorService {
futures
.
add
(
f
);
futures
.
add
(
f
);
execute
(
f
);
execute
(
f
);
}
}
for
(
Future
<
T
>
f
:
futures
)
{
for
(
int
i
=
0
,
size
=
futures
.
size
();
i
<
size
;
i
++)
{
Future
<
T
>
f
=
futures
.
get
(
i
);
if
(!
f
.
isDone
())
{
if
(!
f
.
isDone
())
{
try
{
try
{
f
.
get
();
f
.
get
();
...
@@ -248,8 +249,8 @@ public abstract class AbstractExecutorService implements ExecutorService {
...
@@ -248,8 +249,8 @@ public abstract class AbstractExecutorService implements ExecutorService {
return
futures
;
return
futures
;
}
finally
{
}
finally
{
if
(!
done
)
if
(!
done
)
for
(
Future
<
T
>
f
:
futures
)
for
(
int
i
=
0
,
size
=
futures
.
size
();
i
<
size
;
i
++
)
f
.
cancel
(
true
);
f
utures
.
get
(
i
)
.
cancel
(
true
);
}
}
}
}
...
@@ -259,25 +260,26 @@ public abstract class AbstractExecutorService implements ExecutorService {
...
@@ -259,25 +260,26 @@ public abstract class AbstractExecutorService implements ExecutorService {
if
(
tasks
==
null
)
if
(
tasks
==
null
)
throw
new
NullPointerException
();
throw
new
NullPointerException
();
long
nanos
=
unit
.
toNanos
(
timeout
);
long
nanos
=
unit
.
toNanos
(
timeout
);
List
<
Future
<
T
>>
futures
=
new
ArrayList
<
Future
<
T
>>(
tasks
.
size
());
Array
List
<
Future
<
T
>>
futures
=
new
ArrayList
<
Future
<
T
>>(
tasks
.
size
());
boolean
done
=
false
;
boolean
done
=
false
;
try
{
try
{
for
(
Callable
<
T
>
t
:
tasks
)
for
(
Callable
<
T
>
t
:
tasks
)
futures
.
add
(
newTaskFor
(
t
));
futures
.
add
(
newTaskFor
(
t
));
final
long
deadline
=
System
.
nanoTime
()
+
nanos
;
final
long
deadline
=
System
.
nanoTime
()
+
nanos
;
final
int
size
=
futures
.
size
();
// Interleave time checks and calls to execute in case
// Interleave time checks and calls to execute in case
// executor doesn't have any/much parallelism.
// executor doesn't have any/much parallelism.
Iterator
<
Future
<
T
>>
it
=
futures
.
iterator
();
for
(
int
i
=
0
;
i
<
size
;
i
++)
{
while
(
it
.
hasNext
())
{
execute
((
Runnable
)
futures
.
get
(
i
));
execute
((
Runnable
)(
it
.
next
()));
nanos
=
deadline
-
System
.
nanoTime
();
nanos
=
deadline
-
System
.
nanoTime
();
if
(
nanos
<=
0L
)
if
(
nanos
<=
0L
)
return
futures
;
return
futures
;
}
}
for
(
Future
<
T
>
f
:
futures
)
{
for
(
int
i
=
0
;
i
<
size
;
i
++)
{
Future
<
T
>
f
=
futures
.
get
(
i
);
if
(!
f
.
isDone
())
{
if
(!
f
.
isDone
())
{
if
(
nanos
<=
0L
)
if
(
nanos
<=
0L
)
return
futures
;
return
futures
;
...
@@ -295,8 +297,8 @@ public abstract class AbstractExecutorService implements ExecutorService {
...
@@ -295,8 +297,8 @@ public abstract class AbstractExecutorService implements ExecutorService {
return
futures
;
return
futures
;
}
finally
{
}
finally
{
if
(!
done
)
if
(!
done
)
for
(
Future
<
T
>
f
:
futures
)
for
(
int
i
=
0
,
size
=
futures
.
size
();
i
<
size
;
i
++
)
f
.
cancel
(
true
);
f
utures
.
get
(
i
)
.
cancel
(
true
);
}
}
}
}
...
...
src/share/classes/java/util/concurrent/Callable.java
浏览文件 @
6693c900
...
@@ -38,21 +38,21 @@ package java.util.concurrent;
...
@@ -38,21 +38,21 @@ package java.util.concurrent;
/**
/**
* A task that returns a result and may throw an exception.
* A task that returns a result and may throw an exception.
* Implementors define a single method with no arguments called
* Implementors define a single method with no arguments called
*
<tt>call</tt>
.
*
{@code call}
.
*
*
* <p>The
<tt>Callable</tt>
interface is similar to {@link
* <p>The
{@code Callable}
interface is similar to {@link
* java.lang.Runnable}, in that both are designed for classes whose
* java.lang.Runnable}, in that both are designed for classes whose
* instances are potentially executed by another thread. A
* instances are potentially executed by another thread. A
*
<tt>Runnable</tt>
, however, does not return a result and cannot
*
{@code Runnable}
, however, does not return a result and cannot
* throw a checked exception.
* throw a checked exception.
*
*
* <p>
The {@link Executors} class contains utility methods to
* <p>The {@link Executors} class contains utility methods to
* convert from other common forms to
<tt>Callable</tt>
classes.
* convert from other common forms to
{@code Callable}
classes.
*
*
* @see Executor
* @see Executor
* @since 1.5
* @since 1.5
* @author Doug Lea
* @author Doug Lea
* @param <V> the result type of method
<tt>call</tt>
* @param <V> the result type of method
{@code call}
*/
*/
public
interface
Callable
<
V
>
{
public
interface
Callable
<
V
>
{
/**
/**
...
...
src/share/classes/java/util/concurrent/CancellationException.java
浏览文件 @
6693c900
...
@@ -47,12 +47,12 @@ public class CancellationException extends IllegalStateException {
...
@@ -47,12 +47,12 @@ public class CancellationException extends IllegalStateException {
private
static
final
long
serialVersionUID
=
-
9202173006928992231L
;
private
static
final
long
serialVersionUID
=
-
9202173006928992231L
;
/**
/**
* Constructs a
<tt>CancellationException</tt>
with no detail message.
* Constructs a
{@code CancellationException}
with no detail message.
*/
*/
public
CancellationException
()
{}
public
CancellationException
()
{}
/**
/**
* Constructs a
<tt>CancellationException</tt>
with the specified detail
* Constructs a
{@code CancellationException}
with the specified detail
* message.
* message.
*
*
* @param message the detail message
* @param message the detail message
...
...
src/share/classes/java/util/concurrent/CompletableFuture.java
浏览文件 @
6693c900
...
@@ -1209,7 +1209,7 @@ public class CompletableFuture<T> implements Future<T> {
...
@@ -1209,7 +1209,7 @@ public class CompletableFuture<T> implements Future<T> {
(
r
=
a
.
result
)
!=
null
&&
(
r
=
a
.
result
)
!=
null
&&
compareAndSet
(
0
,
1
))
{
compareAndSet
(
0
,
1
))
{
if
((
r
instanceof
AltResult
)
&&
if
((
r
instanceof
AltResult
)
&&
(
ex
=
((
AltResult
)
r
).
ex
)
!=
null
)
{
(
ex
=
((
AltResult
)
r
).
ex
)
!=
null
)
{
try
{
try
{
t
=
fn
.
apply
(
ex
);
t
=
fn
.
apply
(
ex
);
}
catch
(
Throwable
rex
)
{
}
catch
(
Throwable
rex
)
{
...
@@ -2892,7 +2892,7 @@ public class CompletableFuture<T> implements Future<T> {
...
@@ -2892,7 +2892,7 @@ public class CompletableFuture<T> implements Future<T> {
if
(
r
!=
null
&&
(
d
==
null
||
d
.
compareAndSet
(
0
,
1
)))
{
if
(
r
!=
null
&&
(
d
==
null
||
d
.
compareAndSet
(
0
,
1
)))
{
T
t
=
null
;
Throwable
ex
,
dx
=
null
;
T
t
=
null
;
Throwable
ex
,
dx
=
null
;
if
(
r
instanceof
AltResult
)
{
if
(
r
instanceof
AltResult
)
{
if
((
ex
=
((
AltResult
)
r
).
ex
)
!=
null
)
{
if
((
ex
=
((
AltResult
)
r
).
ex
)
!=
null
)
{
try
{
try
{
t
=
fn
.
apply
(
ex
);
t
=
fn
.
apply
(
ex
);
}
catch
(
Throwable
rex
)
{
}
catch
(
Throwable
rex
)
{
...
...
src/share/classes/java/util/concurrent/CompletionService.java
浏览文件 @
6693c900
...
@@ -38,17 +38,17 @@ package java.util.concurrent;
...
@@ -38,17 +38,17 @@ package java.util.concurrent;
/**
/**
* A service that decouples the production of new asynchronous tasks
* A service that decouples the production of new asynchronous tasks
* from the consumption of the results of completed tasks. Producers
* from the consumption of the results of completed tasks. Producers
*
<tt>submit</tt> tasks for execution. Consumers <tt>take</tt>
*
{@code submit} tasks for execution. Consumers {@code take}
* completed tasks and process their results in the order they
* completed tasks and process their results in the order they
* complete. A
<tt>CompletionService</tt>
can for example be used to
* complete. A
{@code CompletionService}
can for example be used to
* manage asynchronous IO, in which tasks that perform reads are
* manage asynchronous I
/
O, in which tasks that perform reads are
* submitted in one part of a program or system, and then acted upon
* submitted in one part of a program or system, and then acted upon
* in a different part of the program when the reads complete,
* in a different part of the program when the reads complete,
* possibly in a different order than they were requested.
* possibly in a different order than they were requested.
*
*
* <p>Typically, a
<tt>CompletionService</tt>
relies on a separate
* <p>Typically, a
{@code CompletionService}
relies on a separate
* {@link Executor} to actually execute the tasks, in which case the
* {@link Executor} to actually execute the tasks, in which case the
*
<tt>CompletionService</tt>
only manages an internal completion
*
{@code CompletionService}
only manages an internal completion
* queue. The {@link ExecutorCompletionService} class provides an
* queue. The {@link ExecutorCompletionService} class provides an
* implementation of this approach.
* implementation of this approach.
*
*
...
@@ -80,7 +80,7 @@ public interface CompletionService<V> {
...
@@ -80,7 +80,7 @@ public interface CompletionService<V> {
* @param task the task to submit
* @param task the task to submit
* @param result the result to return upon successful completion
* @param result the result to return upon successful completion
* @return a Future representing pending completion of the task,
* @return a Future representing pending completion of the task,
* and whose
<tt>get()</tt>
method will return the given
* and whose
{@code get()}
method will return the given
* result value upon completion
* result value upon completion
* @throws RejectedExecutionException if the task cannot be
* @throws RejectedExecutionException if the task cannot be
* scheduled for execution
* scheduled for execution
...
@@ -99,10 +99,10 @@ public interface CompletionService<V> {
...
@@ -99,10 +99,10 @@ public interface CompletionService<V> {
/**
/**
* Retrieves and removes the Future representing the next
* Retrieves and removes the Future representing the next
* completed task
or <tt>null</tt>
if none are present.
* completed task
, or {@code null}
if none are present.
*
*
* @return the Future representing the next completed task, or
* @return the Future representing the next completed task, or
*
<tt>null</tt>
if none are present
*
{@code null}
if none are present
*/
*/
Future
<
V
>
poll
();
Future
<
V
>
poll
();
...
@@ -112,11 +112,11 @@ public interface CompletionService<V> {
...
@@ -112,11 +112,11 @@ public interface CompletionService<V> {
* time if none are yet present.
* time if none are yet present.
*
*
* @param timeout how long to wait before giving up, in units of
* @param timeout how long to wait before giving up, in units of
*
<tt>unit</tt>
*
{@code unit}
* @param unit a
<tt>TimeUnit</tt>
determining how to interpret the
* @param unit a
{@code TimeUnit}
determining how to interpret the
*
<tt>timeout</tt>
parameter
*
{@code timeout}
parameter
* @return the Future representing the next completed task or
* @return the Future representing the next completed task or
*
<tt>null</tt>
if the specified waiting time elapses
*
{@code null}
if the specified waiting time elapses
* before one is present
* before one is present
* @throws InterruptedException if interrupted while waiting
* @throws InterruptedException if interrupted while waiting
*/
*/
...
...
src/share/classes/java/util/concurrent/CountedCompleter.java
浏览文件 @
6693c900
...
@@ -37,14 +37,15 @@ package java.util.concurrent;
...
@@ -37,14 +37,15 @@ package java.util.concurrent;
/**
/**
* A {@link ForkJoinTask} with a completion action performed when
* A {@link ForkJoinTask} with a completion action performed when
* triggered and there are no remaining pending
* triggered and there are no remaining pending
actions.
*
actions.
CountedCompleters are in general more robust in the
* CountedCompleters are in general more robust in the
* presence of subtask stalls and blockage than are other forms of
* presence of subtask stalls and blockage than are other forms of
* ForkJoinTasks, but are less intuitive to program. Uses of
* ForkJoinTasks, but are less intuitive to program. Uses of
* CountedCompleter are similar to those of other completion based
* CountedCompleter are similar to those of other completion based
* components (such as {@link java.nio.channels.CompletionHandler})
* components (such as {@link java.nio.channels.CompletionHandler})
* except that multiple <em>pending</em> completions may be necessary
* except that multiple <em>pending</em> completions may be necessary
* to trigger the completion action {@link #onCompletion}, not just one.
* to trigger the completion action {@link #onCompletion(CountedCompleter)},
* not just one.
* Unless initialized otherwise, the {@linkplain #getPendingCount pending
* Unless initialized otherwise, the {@linkplain #getPendingCount pending
* count} starts at zero, but may be (atomically) changed using
* count} starts at zero, but may be (atomically) changed using
* methods {@link #setPendingCount}, {@link #addToPendingCount}, and
* methods {@link #setPendingCount}, {@link #addToPendingCount}, and
...
@@ -69,9 +70,10 @@ package java.util.concurrent;
...
@@ -69,9 +70,10 @@ package java.util.concurrent;
* <p>A concrete CountedCompleter class must define method {@link
* <p>A concrete CountedCompleter class must define method {@link
* #compute}, that should in most cases (as illustrated below), invoke
* #compute}, that should in most cases (as illustrated below), invoke
* {@code tryComplete()} once before returning. The class may also
* {@code tryComplete()} once before returning. The class may also
* optionally override method {@link #onCompletion} to perform an
* optionally override method {@link #onCompletion(CountedCompleter)}
* action upon normal completion, and method {@link
* to perform an action upon normal completion, and method
* #onExceptionalCompletion} to perform an action upon any exception.
* {@link #onExceptionalCompletion(Throwable, CountedCompleter)} to
* perform an action upon any exception.
*
*
* <p>CountedCompleters most often do not bear results, in which case
* <p>CountedCompleters most often do not bear results, in which case
* they are normally declared as {@code CountedCompleter<Void>}, and
* they are normally declared as {@code CountedCompleter<Void>}, and
...
@@ -92,13 +94,14 @@ package java.util.concurrent;
...
@@ -92,13 +94,14 @@ package java.util.concurrent;
* only as an internal helper for other computations, so its own task
* only as an internal helper for other computations, so its own task
* status (as reported in methods such as {@link ForkJoinTask#isDone})
* status (as reported in methods such as {@link ForkJoinTask#isDone})
* is arbitrary; this status changes only upon explicit invocations of
* is arbitrary; this status changes only upon explicit invocations of
* {@link #complete}, {@link ForkJoinTask#cancel}, {@link
* {@link #complete}, {@link ForkJoinTask#cancel},
* ForkJoinTask#completeExceptionally} or upon exceptional completion
* {@link ForkJoinTask#completeExceptionally(Throwable)} or upon
* of method {@code compute}. Upon any exceptional completion, the
* exceptional completion of method {@code compute}. Upon any
* exception may be relayed to a task's completer (and its completer,
* exceptional completion, the exception may be relayed to a task's
* and so on), if one exists and it has not otherwise already
* completer (and its completer, and so on), if one exists and it has
* completed. Similarly, cancelling an internal CountedCompleter has
* not otherwise already completed. Similarly, cancelling an internal
* only a local effect on that completer, so is not often useful.
* CountedCompleter has only a local effect on that completer, so is
* not often useful.
*
*
* <p><b>Sample Usages.</b>
* <p><b>Sample Usages.</b>
*
*
...
@@ -125,8 +128,8 @@ package java.util.concurrent;
...
@@ -125,8 +128,8 @@ package java.util.concurrent;
* improve load balancing. In the recursive case, the second of each
* improve load balancing. In the recursive case, the second of each
* pair of subtasks to finish triggers completion of its parent
* pair of subtasks to finish triggers completion of its parent
* (because no result combination is performed, the default no-op
* (because no result combination is performed, the default no-op
* implementation of method {@code onCompletion} is not overridden).
A
* implementation of method {@code onCompletion} is not overridden).
* static utility method sets up the base task and invokes it
*
A
static utility method sets up the base task and invokes it
* (here, implicitly using the {@link ForkJoinPool#commonPool()}).
* (here, implicitly using the {@link ForkJoinPool#commonPool()}).
*
*
* <pre> {@code
* <pre> {@code
...
@@ -181,12 +184,11 @@ package java.util.concurrent;
...
@@ -181,12 +184,11 @@ package java.util.concurrent;
* }
* }
* }</pre>
* }</pre>
*
*
* As a further improvement, notice that the left task need not even
* As a further improvement, notice that the left task need not even exist.
* exist. Instead of creating a new one, we can iterate using the
* Instead of creating a new one, we can iterate using the original task,
* original task, and add a pending count for each fork. Additionally,
* and add a pending count for each fork. Additionally, because no task
* because no task in this tree implements an {@link #onCompletion}
* in this tree implements an {@link #onCompletion(CountedCompleter)} method,
* method, {@code tryComplete()} can be replaced with {@link
* {@code tryComplete()} can be replaced with {@link #propagateCompletion}.
* #propagateCompletion}.
*
*
* <pre> {@code
* <pre> {@code
* class ForEach<E> ...
* class ForEach<E> ...
...
@@ -253,7 +255,7 @@ package java.util.concurrent;
...
@@ -253,7 +255,7 @@ package java.util.concurrent;
* public static <E> E search(E[] array) {
* public static <E> E search(E[] array) {
* return new Searcher<E>(null, array, new AtomicReference<E>(), 0, array.length).invoke();
* return new Searcher<E>(null, array, new AtomicReference<E>(), 0, array.length).invoke();
* }
* }
*}}</pre>
*
}}</pre>
*
*
* In this example, as well as others in which tasks have no other
* In this example, as well as others in which tasks have no other
* effects except to compareAndSet a common result, the trailing
* effects except to compareAndSet a common result, the trailing
...
@@ -264,7 +266,7 @@ package java.util.concurrent;
...
@@ -264,7 +266,7 @@ package java.util.concurrent;
*
*
* <p><b>Recording subtasks.</b> CountedCompleter tasks that combine
* <p><b>Recording subtasks.</b> CountedCompleter tasks that combine
* results of multiple subtasks usually need to access these results
* results of multiple subtasks usually need to access these results
* in method {@link #onCompletion}. As illustrated in the following
* in method {@link #onCompletion
(CountedCompleter)
}. As illustrated in the following
* class (that performs a simplified form of map-reduce where mappings
* class (that performs a simplified form of map-reduce where mappings
* and reductions are all of type {@code E}), one way to do this in
* and reductions are all of type {@code E}), one way to do this in
* divide and conquer designs is to have each subtask record its
* divide and conquer designs is to have each subtask record its
...
@@ -365,7 +367,7 @@ package java.util.concurrent;
...
@@ -365,7 +367,7 @@ package java.util.concurrent;
* while (h - l >= 2) {
* while (h - l >= 2) {
* int mid = (l + h) >>> 1;
* int mid = (l + h) >>> 1;
* addToPendingCount(1);
* addToPendingCount(1);
* (forks = new MapReducer(this, array, mapper, reducer, mid, h, forks)).fork;
* (forks = new MapReducer(this, array, mapper, reducer, mid, h, forks)).fork
()
;
* h = mid;
* h = mid;
* }
* }
* if (h > l)
* if (h > l)
...
@@ -386,7 +388,7 @@ package java.util.concurrent;
...
@@ -386,7 +388,7 @@ package java.util.concurrent;
*
*
* <p><b>Triggers.</b> Some CountedCompleters are themselves never
* <p><b>Triggers.</b> Some CountedCompleters are themselves never
* forked, but instead serve as bits of plumbing in other designs;
* forked, but instead serve as bits of plumbing in other designs;
* including those in which the completion of one o
f
more async tasks
* including those in which the completion of one o
r
more async tasks
* triggers another async task. For example:
* triggers another async task. For example:
*
*
* <pre> {@code
* <pre> {@code
...
@@ -460,27 +462,28 @@ public abstract class CountedCompleter<T> extends ForkJoinTask<T> {
...
@@ -460,27 +462,28 @@ public abstract class CountedCompleter<T> extends ForkJoinTask<T> {
* (and/or links to other results) to combine.
* (and/or links to other results) to combine.
*
*
* @param caller the task invoking this method (which may
* @param caller the task invoking this method (which may
* be this task itself)
.
* be this task itself)
*/
*/
public
void
onCompletion
(
CountedCompleter
<?>
caller
)
{
public
void
onCompletion
(
CountedCompleter
<?>
caller
)
{
}
}
/**
/**
* Performs an action when method {@link #completeExceptionally}
* Performs an action when method {@link
* is invoked or method {@link #compute} throws an exception, and
* #completeExceptionally(Throwable)} is invoked or method {@link
* this task has not otherwise already completed normally. On
* #compute} throws an exception, and this task has not already
* entry to this method, this task {@link
* otherwise completed normally. On entry to this method, this task
* ForkJoinTask#isCompletedAbnormally}. The return value of this
* {@link ForkJoinTask#isCompletedAbnormally}. The return value
* method controls further propagation: If {@code true} and this
* of this method controls further propagation: If {@code true}
* task has a completer, then this completer is also completed
* and this task has a completer that has not completed, then that
* exceptionally. The default implementation of this method does
* completer is also completed exceptionally, with the same
* nothing except return {@code true}.
* exception as this completer. The default implementation of
* this method does nothing except return {@code true}.
*
*
* @param ex the exception
* @param ex the exception
* @param caller the task invoking this method (which may
* @param caller the task invoking this method (which may
* be this task itself)
.
* be this task itself)
* @return
true
if this exception should be propagated to this
* @return
{@code true}
if this exception should be propagated to this
* task's completer, if one exists
.
* task's completer, if one exists
*/
*/
public
boolean
onExceptionalCompletion
(
Throwable
ex
,
CountedCompleter
<?>
caller
)
{
public
boolean
onExceptionalCompletion
(
Throwable
ex
,
CountedCompleter
<?>
caller
)
{
return
true
;
return
true
;
...
@@ -520,8 +523,7 @@ public abstract class CountedCompleter<T> extends ForkJoinTask<T> {
...
@@ -520,8 +523,7 @@ public abstract class CountedCompleter<T> extends ForkJoinTask<T> {
* @param delta the value to add
* @param delta the value to add
*/
*/
public
final
void
addToPendingCount
(
int
delta
)
{
public
final
void
addToPendingCount
(
int
delta
)
{
int
c
;
// note: can replace with intrinsic in jdk8
U
.
getAndAddInt
(
this
,
PENDING
,
delta
);
do
{}
while
(!
U
.
compareAndSwapInt
(
this
,
PENDING
,
c
=
pending
,
c
+
delta
));
}
}
/**
/**
...
@@ -530,7 +532,7 @@ public abstract class CountedCompleter<T> extends ForkJoinTask<T> {
...
@@ -530,7 +532,7 @@ public abstract class CountedCompleter<T> extends ForkJoinTask<T> {
*
*
* @param expected the expected value
* @param expected the expected value
* @param count the new value
* @param count the new value
* @return
true
if successful
* @return
{@code true}
if successful
*/
*/
public
final
boolean
compareAndSetPendingCount
(
int
expected
,
int
count
)
{
public
final
boolean
compareAndSetPendingCount
(
int
expected
,
int
count
)
{
return
U
.
compareAndSwapInt
(
this
,
PENDING
,
expected
,
count
);
return
U
.
compareAndSwapInt
(
this
,
PENDING
,
expected
,
count
);
...
@@ -564,9 +566,9 @@ public abstract class CountedCompleter<T> extends ForkJoinTask<T> {
...
@@ -564,9 +566,9 @@ public abstract class CountedCompleter<T> extends ForkJoinTask<T> {
/**
/**
* If the pending count is nonzero, decrements the count;
* If the pending count is nonzero, decrements the count;
* otherwise invokes {@link #onCompletion
} and then similarly
* otherwise invokes {@link #onCompletion
(CountedCompleter)}
*
tries to complete this task's completer, if one exists
,
*
and then similarly tries to complete this task's completer
,
* else marks this task as complete.
*
if one exists,
else marks this task as complete.
*/
*/
public
final
void
tryComplete
()
{
public
final
void
tryComplete
()
{
CountedCompleter
<?>
a
=
this
,
s
=
a
;
CountedCompleter
<?>
a
=
this
,
s
=
a
;
...
@@ -585,12 +587,12 @@ public abstract class CountedCompleter<T> extends ForkJoinTask<T> {
...
@@ -585,12 +587,12 @@ public abstract class CountedCompleter<T> extends ForkJoinTask<T> {
/**
/**
* Equivalent to {@link #tryComplete} but does not invoke {@link
* Equivalent to {@link #tryComplete} but does not invoke {@link
* #onCompletion
} along the completion path: If the pending count
* #onCompletion
(CountedCompleter)} along the completion path:
*
is nonzero, decrements the count; otherwise, similarly tries to
*
If the pending count is nonzero, decrements the count;
*
complete this task's completer, if one exists, else marks this
*
otherwise, similarly tries to complete this task's completer, if
*
task as complete. This method may be useful in cases wher
e
*
one exists, else marks this task as complete. This method may b
e
*
{@code onCompletion} should not, or need not, be invoked for
*
useful in cases where {@code onCompletion} should not, or need
* each completer in a computation.
*
not, be invoked for
each completer in a computation.
*/
*/
public
final
void
propagateCompletion
()
{
public
final
void
propagateCompletion
()
{
CountedCompleter
<?>
a
=
this
,
s
=
a
;
CountedCompleter
<?>
a
=
this
,
s
=
a
;
...
@@ -607,13 +609,15 @@ public abstract class CountedCompleter<T> extends ForkJoinTask<T> {
...
@@ -607,13 +609,15 @@ public abstract class CountedCompleter<T> extends ForkJoinTask<T> {
}
}
/**
/**
* Regardless of pending count, invokes {@link #onCompletion},
* Regardless of pending count, invokes
* marks this task as complete and further triggers {@link
* {@link #onCompletion(CountedCompleter)}, marks this task as
* #tryComplete} on this task's completer, if one exists. The
* complete and further triggers {@link #tryComplete} on this
* given rawResult is used as an argument to {@link #setRawResult}
* task's completer, if one exists. The given rawResult is
* before invoking {@link #onCompletion} or marking this task as
* used as an argument to {@link #setRawResult} before invoking
* complete; its value is meaningful only for classes overriding
* {@link #onCompletion(CountedCompleter)} or marking this task
* {@code setRawResult}.
* as complete; its value is meaningful only for classes
* overriding {@code setRawResult}. This method does not modify
* the pending count.
*
*
* <p>This method may be useful when forcing completion as soon as
* <p>This method may be useful when forcing completion as soon as
* any one (versus all) of several subtask results are obtained.
* any one (versus all) of several subtask results are obtained.
...
@@ -632,7 +636,6 @@ public abstract class CountedCompleter<T> extends ForkJoinTask<T> {
...
@@ -632,7 +636,6 @@ public abstract class CountedCompleter<T> extends ForkJoinTask<T> {
p
.
tryComplete
();
p
.
tryComplete
();
}
}
/**
/**
* If this task's pending count is zero, returns this task;
* If this task's pending count is zero, returns this task;
* otherwise decrements its pending count and returns {@code
* otherwise decrements its pending count and returns {@code
...
@@ -653,8 +656,8 @@ public abstract class CountedCompleter<T> extends ForkJoinTask<T> {
...
@@ -653,8 +656,8 @@ public abstract class CountedCompleter<T> extends ForkJoinTask<T> {
/**
/**
* If this task does not have a completer, invokes {@link
* If this task does not have a completer, invokes {@link
* ForkJoinTask#quietlyComplete} and returns {@code null}. Or, if
* ForkJoinTask#quietlyComplete} and returns {@code null}. Or, if
* th
is task's pending count is non-zero, decrements its pending
* th
e completer's pending count is non-zero, decrements that
* count and returns {@code null}. Otherwise, returns the
*
pending
count and returns {@code null}. Otherwise, returns the
* completer. This method can be used as part of a completion
* completer. This method can be used as part of a completion
* traversal loop for homogeneous task hierarchies:
* traversal loop for homogeneous task hierarchies:
*
*
...
@@ -690,14 +693,35 @@ public abstract class CountedCompleter<T> extends ForkJoinTask<T> {
...
@@ -690,14 +693,35 @@ public abstract class CountedCompleter<T> extends ForkJoinTask<T> {
}
}
}
}
/**
* If this task has not completed, attempts to process at most the
* given number of other unprocessed tasks for which this task is
* on the completion path, if any are known to exist.
*
* @param maxTasks the maximum number of tasks to process. If
* less than or equal to zero, then no tasks are
* processed.
*/
public
final
void
helpComplete
(
int
maxTasks
)
{
Thread
t
;
ForkJoinWorkerThread
wt
;
if
(
maxTasks
>
0
&&
status
>=
0
)
{
if
((
t
=
Thread
.
currentThread
())
instanceof
ForkJoinWorkerThread
)
(
wt
=
(
ForkJoinWorkerThread
)
t
).
pool
.
helpComplete
(
wt
.
workQueue
,
this
,
maxTasks
);
else
ForkJoinPool
.
common
.
externalHelpComplete
(
this
,
maxTasks
);
}
}
/**
/**
* Supports ForkJoinTask exception propagation.
* Supports ForkJoinTask exception propagation.
*/
*/
void
internalPropagateException
(
Throwable
ex
)
{
void
internalPropagateException
(
Throwable
ex
)
{
CountedCompleter
<?>
a
=
this
,
s
=
a
;
CountedCompleter
<?>
a
=
this
,
s
=
a
;
while
(
a
.
onExceptionalCompletion
(
ex
,
s
)
&&
while
(
a
.
onExceptionalCompletion
(
ex
,
s
)
&&
(
a
=
(
s
=
a
).
completer
)
!=
null
&&
a
.
status
>=
0
)
(
a
=
(
s
=
a
).
completer
)
!=
null
&&
a
.
status
>=
0
&&
a
.
recordExceptionalCompletion
(
ex
);
a
.
recordExceptionalCompletion
(
ex
)
==
EXCEPTIONAL
)
;
}
}
/**
/**
...
...
src/share/classes/java/util/concurrent/ExecutionException.java
浏览文件 @
6693c900
...
@@ -48,14 +48,14 @@ public class ExecutionException extends Exception {
...
@@ -48,14 +48,14 @@ public class ExecutionException extends Exception {
private
static
final
long
serialVersionUID
=
7830266012832686185L
;
private
static
final
long
serialVersionUID
=
7830266012832686185L
;
/**
/**
* Constructs an
<tt>ExecutionException</tt>
with no detail message.
* Constructs an
{@code ExecutionException}
with no detail message.
* The cause is not initialized, and may subsequently be
* The cause is not initialized, and may subsequently be
* initialized by a call to {@link #initCause(Throwable) initCause}.
* initialized by a call to {@link #initCause(Throwable) initCause}.
*/
*/
protected
ExecutionException
()
{
}
protected
ExecutionException
()
{
}
/**
/**
* Constructs an
<tt>ExecutionException</tt>
with the specified detail
* Constructs an
{@code ExecutionException}
with the specified detail
* message. The cause is not initialized, and may subsequently be
* message. The cause is not initialized, and may subsequently be
* initialized by a call to {@link #initCause(Throwable) initCause}.
* initialized by a call to {@link #initCause(Throwable) initCause}.
*
*
...
@@ -66,7 +66,7 @@ public class ExecutionException extends Exception {
...
@@ -66,7 +66,7 @@ public class ExecutionException extends Exception {
}
}
/**
/**
* Constructs an
<tt>ExecutionException</tt>
with the specified detail
* Constructs an
{@code ExecutionException}
with the specified detail
* message and cause.
* message and cause.
*
*
* @param message the detail message
* @param message the detail message
...
@@ -78,7 +78,7 @@ public class ExecutionException extends Exception {
...
@@ -78,7 +78,7 @@ public class ExecutionException extends Exception {
}
}
/**
/**
* Constructs an
<tt>ExecutionException</tt>
with the specified cause.
* Constructs an
{@code ExecutionException}
with the specified cause.
* The detail message is set to {@code (cause == null ? null :
* The detail message is set to {@code (cause == null ? null :
* cause.toString())} (which typically contains the class and
* cause.toString())} (which typically contains the class and
* detail message of {@code cause}).
* detail message of {@code cause}).
...
...
src/share/classes/java/util/concurrent/Executor.java
浏览文件 @
6693c900
...
@@ -39,9 +39,9 @@ package java.util.concurrent;
...
@@ -39,9 +39,9 @@ package java.util.concurrent;
* An object that executes submitted {@link Runnable} tasks. This
* An object that executes submitted {@link Runnable} tasks. This
* interface provides a way of decoupling task submission from the
* interface provides a way of decoupling task submission from the
* mechanics of how each task will be run, including details of thread
* mechanics of how each task will be run, including details of thread
* use, scheduling, etc. An
<tt>Executor</tt>
is normally used
* use, scheduling, etc. An
{@code Executor}
is normally used
* instead of explicitly creating threads. For example, rather than
* instead of explicitly creating threads. For example, rather than
* invoking
<tt>new Thread(new(RunnableTask())).start()</tt>
for each
* invoking
{@code new Thread(new(RunnableTask())).start()}
for each
* of a set of tasks, you might use:
* of a set of tasks, you might use:
*
*
* <pre>
* <pre>
...
@@ -51,7 +51,7 @@ package java.util.concurrent;
...
@@ -51,7 +51,7 @@ package java.util.concurrent;
* ...
* ...
* </pre>
* </pre>
*
*
* However, the
<tt>Executor</tt>
interface does not strictly
* However, the
{@code Executor}
interface does not strictly
* require that execution be asynchronous. In the simplest case, an
* require that execution be asynchronous. In the simplest case, an
* executor can run the submitted task immediately in the caller's
* executor can run the submitted task immediately in the caller's
* thread:
* thread:
...
@@ -74,7 +74,7 @@ package java.util.concurrent;
...
@@ -74,7 +74,7 @@ package java.util.concurrent;
* }
* }
* }}</pre>
* }}</pre>
*
*
* Many
<tt>Executor</tt>
implementations impose some sort of
* Many
{@code Executor}
implementations impose some sort of
* limitation on how and when tasks are scheduled. The executor below
* limitation on how and when tasks are scheduled. The executor below
* serializes the submission of tasks to a second executor,
* serializes the submission of tasks to a second executor,
* illustrating a composite executor.
* illustrating a composite executor.
...
@@ -111,7 +111,7 @@ package java.util.concurrent;
...
@@ -111,7 +111,7 @@ package java.util.concurrent;
* }
* }
* }}</pre>
* }}</pre>
*
*
* The
<tt>Executor</tt>
implementations provided in this package
* The
{@code Executor}
implementations provided in this package
* implement {@link ExecutorService}, which is a more extensive
* implement {@link ExecutorService}, which is a more extensive
* interface. The {@link ThreadPoolExecutor} class provides an
* interface. The {@link ThreadPoolExecutor} class provides an
* extensible thread pool implementation. The {@link Executors} class
* extensible thread pool implementation. The {@link Executors} class
...
@@ -130,11 +130,11 @@ public interface Executor {
...
@@ -130,11 +130,11 @@ public interface Executor {
/**
/**
* Executes the given command at some time in the future. The command
* Executes the given command at some time in the future. The command
* may execute in a new thread, in a pooled thread, or in the calling
* may execute in a new thread, in a pooled thread, or in the calling
* thread, at the discretion of the
<tt>Executor</tt>
implementation.
* thread, at the discretion of the
{@code Executor}
implementation.
*
*
* @param command the runnable task
* @param command the runnable task
* @throws RejectedExecutionException if this task cannot be
* @throws RejectedExecutionException if this task cannot be
* accepted for execution
.
* accepted for execution
* @throws NullPointerException if command is null
* @throws NullPointerException if command is null
*/
*/
void
execute
(
Runnable
command
);
void
execute
(
Runnable
command
);
...
...
src/share/classes/java/util/concurrent/ExecutorService.java
浏览文件 @
6693c900
...
@@ -42,21 +42,21 @@ import java.util.Collection;
...
@@ -42,21 +42,21 @@ import java.util.Collection;
* methods that can produce a {@link Future} for tracking progress of
* methods that can produce a {@link Future} for tracking progress of
* one or more asynchronous tasks.
* one or more asynchronous tasks.
*
*
* <p>
An <tt>ExecutorService</tt>
can be shut down, which will cause
* <p>
An {@code ExecutorService}
can be shut down, which will cause
* it to reject new tasks. Two different methods are provided for
* it to reject new tasks. Two different methods are provided for
* shutting down an
<tt>ExecutorService</tt>
. The {@link #shutdown}
* shutting down an
{@code ExecutorService}
. The {@link #shutdown}
* method will allow previously submitted tasks to execute before
* method will allow previously submitted tasks to execute before
* terminating, while the {@link #shutdownNow} method prevents waiting
* terminating, while the {@link #shutdownNow} method prevents waiting
* tasks from starting and attempts to stop currently executing tasks.
* tasks from starting and attempts to stop currently executing tasks.
* Upon termination, an executor has no tasks actively executing, no
* Upon termination, an executor has no tasks actively executing, no
* tasks awaiting execution, and no new tasks can be submitted. An
* tasks awaiting execution, and no new tasks can be submitted. An
* unused
<tt>ExecutorService</tt>
should be shut down to allow
* unused
{@code ExecutorService}
should be shut down to allow
* reclamation of its resources.
* reclamation of its resources.
*
*
* <p>
Method <tt>submit</tt>
extends base method {@link
* <p>
Method {@code submit}
extends base method {@link
* Executor#execute
} by creating and returning a {@link Future} that
* Executor#execute
(Runnable)} by creating and returning a {@link Future}
* can be used to cancel execution and/or wait for completion.
*
that
can be used to cancel execution and/or wait for completion.
* Methods
<tt>invokeAny</tt> and <tt>invokeAll</tt>
perform the most
* Methods
{@code invokeAny} and {@code invokeAll}
perform the most
* commonly useful forms of bulk execution, executing a collection of
* commonly useful forms of bulk execution, executing a collection of
* tasks and then waiting for at least one, or all, to
* tasks and then waiting for at least one, or all, to
* complete. (Class {@link ExecutorCompletionService} can be used to
* complete. (Class {@link ExecutorCompletionService} can be used to
...
@@ -101,9 +101,9 @@ import java.util.Collection;
...
@@ -101,9 +101,9 @@ import java.util.Collection;
* }
* }
* }}</pre>
* }}</pre>
*
*
* The following method shuts down an
<tt>ExecutorService</tt>
in two phases,
* The following method shuts down an
{@code ExecutorService}
in two phases,
* first by calling
<tt>shutdown</tt>
to reject incoming tasks, and then
* first by calling
{@code shutdown}
to reject incoming tasks, and then
* calling
<tt>shutdownNow</tt>
, if necessary, to cancel any lingering tasks:
* calling
{@code shutdownNow}
, if necessary, to cancel any lingering tasks:
*
*
* <pre> {@code
* <pre> {@code
* void shutdownAndAwaitTermination(ExecutorService pool) {
* void shutdownAndAwaitTermination(ExecutorService pool) {
...
@@ -149,8 +149,8 @@ public interface ExecutorService extends Executor {
...
@@ -149,8 +149,8 @@ public interface ExecutorService extends Executor {
* shutting down this ExecutorService may manipulate
* shutting down this ExecutorService may manipulate
* threads that the caller is not permitted to modify
* threads that the caller is not permitted to modify
* because it does not hold {@link
* because it does not hold {@link
* java.lang.RuntimePermission}
<tt>("modifyThread")</tt>
,
* java.lang.RuntimePermission}
{@code ("modifyThread")}
,
* or the security manager's
<tt>checkAccess</tt>
method
* or the security manager's
{@code checkAccess}
method
* denies access.
* denies access.
*/
*/
void
shutdown
();
void
shutdown
();
...
@@ -174,25 +174,25 @@ public interface ExecutorService extends Executor {
...
@@ -174,25 +174,25 @@ public interface ExecutorService extends Executor {
* shutting down this ExecutorService may manipulate
* shutting down this ExecutorService may manipulate
* threads that the caller is not permitted to modify
* threads that the caller is not permitted to modify
* because it does not hold {@link
* because it does not hold {@link
* java.lang.RuntimePermission}
<tt>("modifyThread")</tt>
,
* java.lang.RuntimePermission}
{@code ("modifyThread")}
,
* or the security manager's
<tt>checkAccess</tt>
method
* or the security manager's
{@code checkAccess}
method
* denies access.
* denies access.
*/
*/
List
<
Runnable
>
shutdownNow
();
List
<
Runnable
>
shutdownNow
();
/**
/**
* Returns
<tt>true</tt>
if this executor has been shut down.
* Returns
{@code true}
if this executor has been shut down.
*
*
* @return
<tt>true</tt>
if this executor has been shut down
* @return
{@code true}
if this executor has been shut down
*/
*/
boolean
isShutdown
();
boolean
isShutdown
();
/**
/**
* Returns
<tt>true</tt>
if all tasks have completed following shut down.
* Returns
{@code true}
if all tasks have completed following shut down.
* Note that
<tt>isTerminated</tt> is never <tt>true</tt>
unless
* Note that
{@code isTerminated} is never {@code true}
unless
* either
<tt>shutdown</tt> or <tt>shutdownNow</tt>
was called first.
* either
{@code shutdown} or {@code shutdownNow}
was called first.
*
*
* @return
<tt>true</tt>
if all tasks have completed following shut down
* @return
{@code true}
if all tasks have completed following shut down
*/
*/
boolean
isTerminated
();
boolean
isTerminated
();
...
@@ -203,8 +203,8 @@ public interface ExecutorService extends Executor {
...
@@ -203,8 +203,8 @@ public interface ExecutorService extends Executor {
*
*
* @param timeout the maximum time to wait
* @param timeout the maximum time to wait
* @param unit the time unit of the timeout argument
* @param unit the time unit of the timeout argument
* @return
<tt>true</tt>
if this executor terminated and
* @return
{@code true}
if this executor terminated and
*
<tt>false</tt>
if the timeout elapsed before termination
*
{@code false}
if the timeout elapsed before termination
* @throws InterruptedException if interrupted while waiting
* @throws InterruptedException if interrupted while waiting
*/
*/
boolean
awaitTermination
(
long
timeout
,
TimeUnit
unit
)
boolean
awaitTermination
(
long
timeout
,
TimeUnit
unit
)
...
@@ -213,15 +213,15 @@ public interface ExecutorService extends Executor {
...
@@ -213,15 +213,15 @@ public interface ExecutorService extends Executor {
/**
/**
* Submits a value-returning task for execution and returns a
* Submits a value-returning task for execution and returns a
* Future representing the pending results of the task. The
* Future representing the pending results of the task. The
* Future's
<tt>get</tt>
method will return the task's result upon
* Future's
{@code get}
method will return the task's result upon
* successful completion.
* successful completion.
*
*
* <p>
* <p>
* If you would like to immediately block waiting
* If you would like to immediately block waiting
* for a task, you can use constructions of the form
* for a task, you can use constructions of the form
*
<tt>result = exec.submit(aCallable).get();</tt>
*
{@code result = exec.submit(aCallable).get();}
*
*
* <p>
Note: The {@link Executors} class includes a set of methods
* <p>Note: The {@link Executors} class includes a set of methods
* that can convert some other common closure-like objects,
* that can convert some other common closure-like objects,
* for example, {@link java.security.PrivilegedAction} to
* for example, {@link java.security.PrivilegedAction} to
* {@link Callable} form so they can be submitted.
* {@link Callable} form so they can be submitted.
...
@@ -236,7 +236,7 @@ public interface ExecutorService extends Executor {
...
@@ -236,7 +236,7 @@ public interface ExecutorService extends Executor {
/**
/**
* Submits a Runnable task for execution and returns a Future
* Submits a Runnable task for execution and returns a Future
* representing that task. The Future's
<tt>get</tt>
method will
* representing that task. The Future's
{@code get}
method will
* return the given result upon successful completion.
* return the given result upon successful completion.
*
*
* @param task the task to submit
* @param task the task to submit
...
@@ -250,8 +250,8 @@ public interface ExecutorService extends Executor {
...
@@ -250,8 +250,8 @@ public interface ExecutorService extends Executor {
/**
/**
* Submits a Runnable task for execution and returns a Future
* Submits a Runnable task for execution and returns a Future
* representing that task. The Future's
<tt>get</tt>
method will
* representing that task. The Future's
{@code get}
method will
* return
<tt>null</tt>
upon <em>successful</em> completion.
* return
{@code null}
upon <em>successful</em> completion.
*
*
* @param task the task to submit
* @param task the task to submit
* @return a Future representing pending completion of the task
* @return a Future representing pending completion of the task
...
@@ -264,7 +264,7 @@ public interface ExecutorService extends Executor {
...
@@ -264,7 +264,7 @@ public interface ExecutorService extends Executor {
/**
/**
* Executes the given tasks, returning a list of Futures holding
* Executes the given tasks, returning a list of Futures holding
* their status and results when all complete.
* their status and results when all complete.
* {@link Future#isDone} is
<tt>true</tt>
for each
* {@link Future#isDone} is
{@code true}
for each
* element of the returned list.
* element of the returned list.
* Note that a <em>completed</em> task could have
* Note that a <em>completed</em> task could have
* terminated either normally or by throwing an exception.
* terminated either normally or by throwing an exception.
...
@@ -272,12 +272,12 @@ public interface ExecutorService extends Executor {
...
@@ -272,12 +272,12 @@ public interface ExecutorService extends Executor {
* collection is modified while this operation is in progress.
* collection is modified while this operation is in progress.
*
*
* @param tasks the collection of tasks
* @param tasks the collection of tasks
* @return
A
list of Futures representing the tasks, in the same
* @return
a
list of Futures representing the tasks, in the same
* sequential order as produced by the iterator for the
* sequential order as produced by the iterator for the
* given task list, each of which has completed
.
* given task list, each of which has completed
* @throws InterruptedException if interrupted while waiting, in
* @throws InterruptedException if interrupted while waiting, in
* which case unfinished tasks are cancelled
.
* which case unfinished tasks are cancelled
* @throws NullPointerException if tasks or any of its elements are
<tt>null</tt>
* @throws NullPointerException if tasks or any of its elements are
{@code null}
* @throws RejectedExecutionException if any task cannot be
* @throws RejectedExecutionException if any task cannot be
* scheduled for execution
* scheduled for execution
*/
*/
...
@@ -288,7 +288,7 @@ public interface ExecutorService extends Executor {
...
@@ -288,7 +288,7 @@ public interface ExecutorService extends Executor {
* Executes the given tasks, returning a list of Futures holding
* Executes the given tasks, returning a list of Futures holding
* their status and results
* their status and results
* when all complete or the timeout expires, whichever happens first.
* when all complete or the timeout expires, whichever happens first.
* {@link Future#isDone} is
<tt>true</tt>
for each
* {@link Future#isDone} is
{@code true}
for each
* element of the returned list.
* element of the returned list.
* Upon return, tasks that have not completed are cancelled.
* Upon return, tasks that have not completed are cancelled.
* Note that a <em>completed</em> task could have
* Note that a <em>completed</em> task could have
...
@@ -307,7 +307,7 @@ public interface ExecutorService extends Executor {
...
@@ -307,7 +307,7 @@ public interface ExecutorService extends Executor {
* @throws InterruptedException if interrupted while waiting, in
* @throws InterruptedException if interrupted while waiting, in
* which case unfinished tasks are cancelled
* which case unfinished tasks are cancelled
* @throws NullPointerException if tasks, any of its elements, or
* @throws NullPointerException if tasks, any of its elements, or
* unit are
<tt>null</tt>
* unit are
{@code null}
* @throws RejectedExecutionException if any task cannot be scheduled
* @throws RejectedExecutionException if any task cannot be scheduled
* for execution
* for execution
*/
*/
...
@@ -327,7 +327,7 @@ public interface ExecutorService extends Executor {
...
@@ -327,7 +327,7 @@ public interface ExecutorService extends Executor {
* @return the result returned by one of the tasks
* @return the result returned by one of the tasks
* @throws InterruptedException if interrupted while waiting
* @throws InterruptedException if interrupted while waiting
* @throws NullPointerException if tasks or any element task
* @throws NullPointerException if tasks or any element task
* subject to execution is
<tt>null</tt>
* subject to execution is
{@code null}
* @throws IllegalArgumentException if tasks is empty
* @throws IllegalArgumentException if tasks is empty
* @throws ExecutionException if no task successfully completes
* @throws ExecutionException if no task successfully completes
* @throws RejectedExecutionException if tasks cannot be scheduled
* @throws RejectedExecutionException if tasks cannot be scheduled
...
@@ -348,10 +348,10 @@ public interface ExecutorService extends Executor {
...
@@ -348,10 +348,10 @@ public interface ExecutorService extends Executor {
* @param tasks the collection of tasks
* @param tasks the collection of tasks
* @param timeout the maximum time to wait
* @param timeout the maximum time to wait
* @param unit the time unit of the timeout argument
* @param unit the time unit of the timeout argument
* @return the result returned by one of the tasks
.
* @return the result returned by one of the tasks
* @throws InterruptedException if interrupted while waiting
* @throws InterruptedException if interrupted while waiting
* @throws NullPointerException if tasks, or unit, or any element
* @throws NullPointerException if tasks, or unit, or any element
* task subject to execution is
<tt>null</tt>
* task subject to execution is
{@code null}
* @throws TimeoutException if the given timeout elapses before
* @throws TimeoutException if the given timeout elapses before
* any task successfully completes
* any task successfully completes
* @throws ExecutionException if no task successfully completes
* @throws ExecutionException if no task successfully completes
...
...
src/share/classes/java/util/concurrent/Executors.java
浏览文件 @
6693c900
...
@@ -62,7 +62,7 @@ import sun.security.util.SecurityConstants;
...
@@ -62,7 +62,7 @@ import sun.security.util.SecurityConstants;
* that sets newly created threads to a known state.
* that sets newly created threads to a known state.
* <li> Methods that create and return a {@link Callable}
* <li> Methods that create and return a {@link Callable}
* out of other closure-like forms, so they can be used
* out of other closure-like forms, so they can be used
* in execution methods requiring
<tt>Callable</tt>
.
* in execution methods requiring
{@code Callable}
.
* </ul>
* </ul>
*
*
* @since 1.5
* @since 1.5
...
@@ -73,7 +73,7 @@ public class Executors {
...
@@ -73,7 +73,7 @@ public class Executors {
/**
/**
* Creates a thread pool that reuses a fixed number of threads
* Creates a thread pool that reuses a fixed number of threads
* operating off a shared unbounded queue. At any point, at most
* operating off a shared unbounded queue. At any point, at most
*
<tt>nThreads</tt>
threads will be active processing tasks.
*
{@code nThreads}
threads will be active processing tasks.
* If additional tasks are submitted when all threads are active,
* If additional tasks are submitted when all threads are active,
* they will wait in the queue until a thread is available.
* they will wait in the queue until a thread is available.
* If any thread terminates due to a failure during execution
* If any thread terminates due to a failure during execution
...
@@ -91,11 +91,48 @@ public class Executors {
...
@@ -91,11 +91,48 @@ public class Executors {
new
LinkedBlockingQueue
<
Runnable
>());
new
LinkedBlockingQueue
<
Runnable
>());
}
}
/**
* Creates a thread pool that maintains enough threads to support
* the given parallelism level, and may use multiple queues to
* reduce contention. The parallelism level corresponds to the
* maximum number of threads actively engaged in, or available to
* engage in, task processing. The actual number of threads may
* grow and shrink dynamically. A work-stealing pool makes no
* guarantees about the order in which submitted tasks are
* executed.
*
* @param parallelism the targeted parallelism level
* @return the newly created thread pool
* @throws IllegalArgumentException if {@code parallelism <= 0}
* @since 1.8
*/
public
static
ExecutorService
newWorkStealingPool
(
int
parallelism
)
{
return
new
ForkJoinPool
(
parallelism
,
ForkJoinPool
.
defaultForkJoinWorkerThreadFactory
,
null
,
true
);
}
/**
* Creates a work-stealing thread pool using all
* {@link Runtime#availableProcessors available processors}
* as its target parallelism level.
* @return the newly created thread pool
* @see #newWorkStealingPool(int)
* @since 1.8
*/
public
static
ExecutorService
newWorkStealingPool
()
{
return
new
ForkJoinPool
(
Runtime
.
getRuntime
().
availableProcessors
(),
ForkJoinPool
.
defaultForkJoinWorkerThreadFactory
,
null
,
true
);
}
/**
/**
* Creates a thread pool that reuses a fixed number of threads
* Creates a thread pool that reuses a fixed number of threads
* operating off a shared unbounded queue, using the provided
* operating off a shared unbounded queue, using the provided
* ThreadFactory to create new threads when needed. At any point,
* ThreadFactory to create new threads when needed. At any point,
* at most
<tt>nThreads</tt>
threads will be active processing
* at most
{@code nThreads}
threads will be active processing
* tasks. If additional tasks are submitted when all threads are
* tasks. If additional tasks are submitted when all threads are
* active, they will wait in the queue until a thread is
* active, they will wait in the queue until a thread is
* available. If any thread terminates due to a failure during
* available. If any thread terminates due to a failure during
...
@@ -125,7 +162,7 @@ public class Executors {
...
@@ -125,7 +162,7 @@ public class Executors {
* subsequent tasks.) Tasks are guaranteed to execute
* subsequent tasks.) Tasks are guaranteed to execute
* sequentially, and no more than one task will be active at any
* sequentially, and no more than one task will be active at any
* given time. Unlike the otherwise equivalent
* given time. Unlike the otherwise equivalent
*
<tt>newFixedThreadPool(1)</tt>
the returned executor is
*
{@code newFixedThreadPool(1)}
the returned executor is
* guaranteed not to be reconfigurable to use additional threads.
* guaranteed not to be reconfigurable to use additional threads.
*
*
* @return the newly created single-threaded Executor
* @return the newly created single-threaded Executor
...
@@ -141,7 +178,7 @@ public class Executors {
...
@@ -141,7 +178,7 @@ public class Executors {
* Creates an Executor that uses a single worker thread operating
* Creates an Executor that uses a single worker thread operating
* off an unbounded queue, and uses the provided ThreadFactory to
* off an unbounded queue, and uses the provided ThreadFactory to
* create a new thread when needed. Unlike the otherwise
* create a new thread when needed. Unlike the otherwise
* equivalent
<tt>newFixedThreadPool(1, threadFactory)</tt>
the
* equivalent
{@code newFixedThreadPool(1, threadFactory)}
the
* returned executor is guaranteed not to be reconfigurable to use
* returned executor is guaranteed not to be reconfigurable to use
* additional threads.
* additional threads.
*
*
...
@@ -164,7 +201,7 @@ public class Executors {
...
@@ -164,7 +201,7 @@ public class Executors {
* will reuse previously constructed threads when they are
* will reuse previously constructed threads when they are
* available. These pools will typically improve the performance
* available. These pools will typically improve the performance
* of programs that execute many short-lived asynchronous tasks.
* of programs that execute many short-lived asynchronous tasks.
* Calls to
<tt>execute</tt>
will reuse previously constructed
* Calls to
{@code execute}
will reuse previously constructed
* threads if available. If no existing thread is available, a new
* threads if available. If no existing thread is available, a new
* thread will be created and added to the pool. Threads that have
* thread will be created and added to the pool. Threads that have
* not been used for sixty seconds are terminated and removed from
* not been used for sixty seconds are terminated and removed from
...
@@ -206,7 +243,7 @@ public class Executors {
...
@@ -206,7 +243,7 @@ public class Executors {
* subsequent tasks.) Tasks are guaranteed to execute
* subsequent tasks.) Tasks are guaranteed to execute
* sequentially, and no more than one task will be active at any
* sequentially, and no more than one task will be active at any
* given time. Unlike the otherwise equivalent
* given time. Unlike the otherwise equivalent
*
<tt>newScheduledThreadPool(1)</tt>
the returned executor is
*
{@code newScheduledThreadPool(1)}
the returned executor is
* guaranteed not to be reconfigurable to use additional threads.
* guaranteed not to be reconfigurable to use additional threads.
* @return the newly created scheduled executor
* @return the newly created scheduled executor
*/
*/
...
@@ -223,7 +260,7 @@ public class Executors {
...
@@ -223,7 +260,7 @@ public class Executors {
* place if needed to execute subsequent tasks.) Tasks are
* place if needed to execute subsequent tasks.) Tasks are
* guaranteed to execute sequentially, and no more than one task
* guaranteed to execute sequentially, and no more than one task
* will be active at any given time. Unlike the otherwise
* will be active at any given time. Unlike the otherwise
* equivalent
<tt>newScheduledThreadPool(1, threadFactory)</tt>
* equivalent
{@code newScheduledThreadPool(1, threadFactory)}
* the returned executor is guaranteed not to be reconfigurable to
* the returned executor is guaranteed not to be reconfigurable to
* use additional threads.
* use additional threads.
* @param threadFactory the factory to use when creating new
* @param threadFactory the factory to use when creating new
...
@@ -240,7 +277,7 @@ public class Executors {
...
@@ -240,7 +277,7 @@ public class Executors {
* Creates a thread pool that can schedule commands to run after a
* Creates a thread pool that can schedule commands to run after a
* given delay, or to execute periodically.
* given delay, or to execute periodically.
* @param corePoolSize the number of threads to keep in the pool,
* @param corePoolSize the number of threads to keep in the pool,
* even if they are idle
.
* even if they are idle
* @return a newly created scheduled thread pool
* @return a newly created scheduled thread pool
* @throws IllegalArgumentException if {@code corePoolSize < 0}
* @throws IllegalArgumentException if {@code corePoolSize < 0}
*/
*/
...
@@ -252,9 +289,9 @@ public class Executors {
...
@@ -252,9 +289,9 @@ public class Executors {
* Creates a thread pool that can schedule commands to run after a
* Creates a thread pool that can schedule commands to run after a
* given delay, or to execute periodically.
* given delay, or to execute periodically.
* @param corePoolSize the number of threads to keep in the pool,
* @param corePoolSize the number of threads to keep in the pool,
* even if they are idle
.
* even if they are idle
* @param threadFactory the factory to use when the executor
* @param threadFactory the factory to use when the executor
* creates a new thread
.
* creates a new thread
* @return a newly created scheduled thread pool
* @return a newly created scheduled thread pool
* @throws IllegalArgumentException if {@code corePoolSize < 0}
* @throws IllegalArgumentException if {@code corePoolSize < 0}
* @throws NullPointerException if threadFactory is null
* @throws NullPointerException if threadFactory is null
...
@@ -264,7 +301,6 @@ public class Executors {
...
@@ -264,7 +301,6 @@ public class Executors {
return
new
ScheduledThreadPoolExecutor
(
corePoolSize
,
threadFactory
);
return
new
ScheduledThreadPoolExecutor
(
corePoolSize
,
threadFactory
);
}
}
/**
/**
* Returns an object that delegates all defined {@link
* Returns an object that delegates all defined {@link
* ExecutorService} methods to the given executor, but not any
* ExecutorService} methods to the given executor, but not any
...
@@ -272,7 +308,7 @@ public class Executors {
...
@@ -272,7 +308,7 @@ public class Executors {
* casts. This provides a way to safely "freeze" configuration and
* casts. This provides a way to safely "freeze" configuration and
* disallow tuning of a given concrete implementation.
* disallow tuning of a given concrete implementation.
* @param executor the underlying implementation
* @param executor the underlying implementation
* @return an
<tt>ExecutorService</tt>
instance
* @return an
{@code ExecutorService}
instance
* @throws NullPointerException if executor null
* @throws NullPointerException if executor null
*/
*/
public
static
ExecutorService
unconfigurableExecutorService
(
ExecutorService
executor
)
{
public
static
ExecutorService
unconfigurableExecutorService
(
ExecutorService
executor
)
{
...
@@ -288,7 +324,7 @@ public class Executors {
...
@@ -288,7 +324,7 @@ public class Executors {
* casts. This provides a way to safely "freeze" configuration and
* casts. This provides a way to safely "freeze" configuration and
* disallow tuning of a given concrete implementation.
* disallow tuning of a given concrete implementation.
* @param executor the underlying implementation
* @param executor the underlying implementation
* @return a
<tt>ScheduledExecutorService</tt>
instance
* @return a
{@code ScheduledExecutorService}
instance
* @throws NullPointerException if executor null
* @throws NullPointerException if executor null
*/
*/
public
static
ScheduledExecutorService
unconfigurableScheduledExecutorService
(
ScheduledExecutorService
executor
)
{
public
static
ScheduledExecutorService
unconfigurableScheduledExecutorService
(
ScheduledExecutorService
executor
)
{
...
@@ -303,9 +339,9 @@ public class Executors {
...
@@ -303,9 +339,9 @@ public class Executors {
* same {@link ThreadGroup}. If there is a {@link
* same {@link ThreadGroup}. If there is a {@link
* java.lang.SecurityManager}, it uses the group of {@link
* java.lang.SecurityManager}, it uses the group of {@link
* System#getSecurityManager}, else the group of the thread
* System#getSecurityManager}, else the group of the thread
* invoking this
<tt>defaultThreadFactory</tt>
method. Each new
* invoking this
{@code defaultThreadFactory}
method. Each new
* thread is created as a non-daemon thread with priority set to
* thread is created as a non-daemon thread with priority set to
* the smaller of
<tt>Thread.NORM_PRIORITY</tt>
and the maximum
* the smaller of
{@code Thread.NORM_PRIORITY}
and the maximum
* priority permitted in the thread group. New threads have names
* priority permitted in the thread group. New threads have names
* accessible via {@link Thread#getName} of
* accessible via {@link Thread#getName} of
* <em>pool-N-thread-M</em>, where <em>N</em> is the sequence
* <em>pool-N-thread-M</em>, where <em>N</em> is the sequence
...
@@ -324,30 +360,31 @@ public class Executors {
...
@@ -324,30 +360,31 @@ public class Executors {
* Executors#defaultThreadFactory}, additionally setting the
* Executors#defaultThreadFactory}, additionally setting the
* AccessControlContext and contextClassLoader of new threads to
* AccessControlContext and contextClassLoader of new threads to
* be the same as the thread invoking this
* be the same as the thread invoking this
* <tt>privilegedThreadFactory</tt> method. A new
* {@code privilegedThreadFactory} method. A new
* <tt>privilegedThreadFactory</tt> can be created within an
* {@code privilegedThreadFactory} can be created within an
* {@link AccessController#doPrivileged} action setting the
* {@link AccessController#doPrivileged AccessController.doPrivileged}
* current thread's access control context to create threads with
* action setting the current thread's access control context to
* the selected permission settings holding within that action.
* create threads with the selected permission settings holding
* within that action.
*
*
* <p>
Note that while tasks running within such threads will have
* <p>Note that while tasks running within such threads will have
* the same access control and class loader settings as the
* the same access control and class loader settings as the
* current thread, they need not have the same {@link
* current thread, they need not have the same {@link
* java.lang.ThreadLocal} or {@link
* java.lang.ThreadLocal} or {@link
* java.lang.InheritableThreadLocal} values. If necessary,
* java.lang.InheritableThreadLocal} values. If necessary,
* particular values of thread locals can be set or reset before
* particular values of thread locals can be set or reset before
* any task runs in {@link ThreadPoolExecutor} subclasses using
* any task runs in {@link ThreadPoolExecutor} subclasses using
* {@link ThreadPoolExecutor#beforeExecute
}. Also, if it is
* {@link ThreadPoolExecutor#beforeExecute
(Thread, Runnable)}.
*
necessary to initialize worker threads to have the sam
e
*
Also, if it is necessary to initialize worker threads to hav
e
*
InheritableThreadLocal settings as some other designated
*
the same InheritableThreadLocal settings as some other
*
thread, you can create a custom ThreadFactory in which that
*
designated thread, you can create a custom ThreadFactory in
*
thread waits for and services requests to create others that
*
which that thread waits for and services requests to create
* will inherit its values.
*
others that
will inherit its values.
*
*
* @return a thread factory
* @return a thread factory
* @throws AccessControlException if the current access control
* @throws AccessControlException if the current access control
* context does not have permission to both get and set context
* context does not have permission to both get and set context
* class loader
.
* class loader
*/
*/
public
static
ThreadFactory
privilegedThreadFactory
()
{
public
static
ThreadFactory
privilegedThreadFactory
()
{
return
new
PrivilegedThreadFactory
();
return
new
PrivilegedThreadFactory
();
...
@@ -357,7 +394,7 @@ public class Executors {
...
@@ -357,7 +394,7 @@ public class Executors {
* Returns a {@link Callable} object that, when
* Returns a {@link Callable} object that, when
* called, runs the given task and returns the given result. This
* called, runs the given task and returns the given result. This
* can be useful when applying methods requiring a
* can be useful when applying methods requiring a
*
<tt>Callable</tt>
to an otherwise resultless action.
*
{@code Callable}
to an otherwise resultless action.
* @param task the task to run
* @param task the task to run
* @param result the result to return
* @param result the result to return
* @return a callable object
* @return a callable object
...
@@ -371,7 +408,7 @@ public class Executors {
...
@@ -371,7 +408,7 @@ public class Executors {
/**
/**
* Returns a {@link Callable} object that, when
* Returns a {@link Callable} object that, when
* called, runs the given task and returns
<tt>null</tt>
.
* called, runs the given task and returns
{@code null}
.
* @param task the task to run
* @param task the task to run
* @return a callable object
* @return a callable object
* @throws NullPointerException if task null
* @throws NullPointerException if task null
...
@@ -412,18 +449,17 @@ public class Executors {
...
@@ -412,18 +449,17 @@ public class Executors {
}
}
/**
/**
* Returns a {@link Callable} object that will, when
* Returns a {@link Callable} object that will, when
called,
*
called, execute the given <tt>callable</tt> under the current
*
execute the given {@code callable} under the current access
*
access control context. This method should normally be
*
control context. This method should normally be invoked within
*
invoked within an {@link AccessController#doPrivileged} action
*
an {@link AccessController#doPrivileged AccessController.doPrivileged}
*
to create callables that will, if possible, execute under th
e
*
action to create callables that will, if possible, execut
e
*
selected permission settings holding within that action; or if
*
under the selected permission settings holding within that
* not possible, throw an associated {@link
*
action; or if
not possible, throw an associated {@link
* AccessControlException}.
* AccessControlException}.
* @param callable the underlying task
* @param callable the underlying task
* @return a callable object
* @return a callable object
* @throws NullPointerException if callable null
* @throws NullPointerException if callable null
*
*/
*/
public
static
<
T
>
Callable
<
T
>
privilegedCallable
(
Callable
<
T
>
callable
)
{
public
static
<
T
>
Callable
<
T
>
privilegedCallable
(
Callable
<
T
>
callable
)
{
if
(
callable
==
null
)
if
(
callable
==
null
)
...
@@ -432,22 +468,23 @@ public class Executors {
...
@@ -432,22 +468,23 @@ public class Executors {
}
}
/**
/**
* Returns a {@link Callable} object that will, when
* Returns a {@link Callable} object that will, when called,
* called, execute the given <tt>callable</tt> under the current
* execute the given {@code callable} under the current access
* access control context, with the current context class loader
* control context, with the current context class loader as the
* as the context class loader. This method should normally be
* context class loader. This method should normally be invoked
* invoked within an {@link AccessController#doPrivileged} action
* within an
* to create callables that will, if possible, execute under the
* {@link AccessController#doPrivileged AccessController.doPrivileged}
* selected permission settings holding within that action; or if
* action to create callables that will, if possible, execute
* not possible, throw an associated {@link
* under the selected permission settings holding within that
* action; or if not possible, throw an associated {@link
* AccessControlException}.
* AccessControlException}.
* @param callable the underlying task
*
*
* @param callable the underlying task
* @return a callable object
* @return a callable object
* @throws NullPointerException if callable null
* @throws NullPointerException if callable null
* @throws AccessControlException if the current access control
* @throws AccessControlException if the current access control
* context does not have permission to both set and get context
* context does not have permission to both set and get context
* class loader
.
* class loader
*/
*/
public
static
<
T
>
Callable
<
T
>
privilegedCallableUsingCurrentClassLoader
(
Callable
<
T
>
callable
)
{
public
static
<
T
>
Callable
<
T
>
privilegedCallableUsingCurrentClassLoader
(
Callable
<
T
>
callable
)
{
if
(
callable
==
null
)
if
(
callable
==
null
)
...
@@ -699,7 +736,6 @@ public class Executors {
...
@@ -699,7 +736,6 @@ public class Executors {
}
}
}
}
/** Cannot instantiate. */
/** Cannot instantiate. */
private
Executors
()
{}
private
Executors
()
{}
}
}
src/share/classes/java/util/concurrent/ForkJoinPool.java
浏览文件 @
6693c900
...
@@ -47,6 +47,7 @@ import java.util.concurrent.ExecutorService;
...
@@ -47,6 +47,7 @@ import java.util.concurrent.ExecutorService;
import
java.util.concurrent.Future
;
import
java.util.concurrent.Future
;
import
java.util.concurrent.RejectedExecutionException
;
import
java.util.concurrent.RejectedExecutionException
;
import
java.util.concurrent.RunnableFuture
;
import
java.util.concurrent.RunnableFuture
;
import
java.util.concurrent.ThreadLocalRandom
;
import
java.util.concurrent.TimeUnit
;
import
java.util.concurrent.TimeUnit
;
/**
/**
...
@@ -79,9 +80,9 @@ import java.util.concurrent.TimeUnit;
...
@@ -79,9 +80,9 @@ import java.util.concurrent.TimeUnit;
* level; by default, equal to the number of available processors. The
* level; by default, equal to the number of available processors. The
* pool attempts to maintain enough active (or available) threads by
* pool attempts to maintain enough active (or available) threads by
* dynamically adding, suspending, or resuming internal worker
* dynamically adding, suspending, or resuming internal worker
* threads, even if some tasks are stalled waiting to join
* threads, even if some tasks are stalled waiting to join
others.
*
others. However, no such adjustments are guaranteed in the face of
*
However, no such adjustments are guaranteed in the face of blocked
*
blocked
I/O or other unmanaged synchronization. The nested {@link
* I/O or other unmanaged synchronization. The nested {@link
* ManagedBlocker} interface enables extension of the kinds of
* ManagedBlocker} interface enables extension of the kinds of
* synchronization accommodated.
* synchronization accommodated.
*
*
...
@@ -157,6 +158,7 @@ import java.util.concurrent.TimeUnit;
...
@@ -157,6 +158,7 @@ import java.util.concurrent.TimeUnit;
* @since 1.7
* @since 1.7
* @author Doug Lea
* @author Doug Lea
*/
*/
@sun
.
misc
.
Contended
public
class
ForkJoinPool
extends
AbstractExecutorService
{
public
class
ForkJoinPool
extends
AbstractExecutorService
{
/*
/*
...
@@ -189,32 +191,35 @@ public class ForkJoinPool extends AbstractExecutorService {
...
@@ -189,32 +191,35 @@ public class ForkJoinPool extends AbstractExecutorService {
* (http://research.sun.com/scalable/pubs/index.html) and
* (http://research.sun.com/scalable/pubs/index.html) and
* "Idempotent work stealing" by Michael, Saraswat, and Vechev,
* "Idempotent work stealing" by Michael, Saraswat, and Vechev,
* PPoPP 2009 (http://portal.acm.org/citation.cfm?id=1504186).
* PPoPP 2009 (http://portal.acm.org/citation.cfm?id=1504186).
* The main differences ultimately stem from GC requirements that
* See also "Correct and Efficient Work-Stealing for Weak Memory
* we null out taken slots as soon as we can, to maintain as small
* Models" by Le, Pop, Cohen, and Nardelli, PPoPP 2013
* a footprint as possible even in programs generating huge
* (http://www.di.ens.fr/~zappa/readings/ppopp13.pdf) for an
* numbers of tasks. To accomplish this, we shift the CAS
* analysis of memory ordering (atomic, volatile etc) issues. The
* arbitrating pop vs poll (steal) from being on the indices
* main differences ultimately stem from GC requirements that we
* ("base" and "top") to the slots themselves. So, both a
* null out taken slots as soon as we can, to maintain as small a
* successful pop and poll mainly entail a CAS of a slot from
* footprint as possible even in programs generating huge numbers
* non-null to null. Because we rely on CASes of references, we
* of tasks. To accomplish this, we shift the CAS arbitrating pop
* do not need tag bits on base or top. They are simple ints as
* vs poll (steal) from being on the indices ("base" and "top") to
* used in any circular array-based queue (see for example
* the slots themselves. So, both a successful pop and poll
* ArrayDeque). Updates to the indices must still be ordered in a
* mainly entail a CAS of a slot from non-null to null. Because
* way that guarantees that top == base means the queue is empty,
* we rely on CASes of references, we do not need tag bits on base
* but otherwise may err on the side of possibly making the queue
* or top. They are simple ints as used in any circular
* appear nonempty when a push, pop, or poll have not fully
* array-based queue (see for example ArrayDeque). Updates to the
* committed. Note that this means that the poll operation,
* indices must still be ordered in a way that guarantees that top
* considered individually, is not wait-free. One thief cannot
* == base means the queue is empty, but otherwise may err on the
* successfully continue until another in-progress one (or, if
* side of possibly making the queue appear nonempty when a push,
* previously empty, a push) completes. However, in the
* pop, or poll have not fully committed. Note that this means
* aggregate, we ensure at least probabilistic non-blockingness.
* that the poll operation, considered individually, is not
* If an attempted steal fails, a thief always chooses a different
* wait-free. One thief cannot successfully continue until another
* random victim target to try next. So, in order for one thief to
* in-progress one (or, if previously empty, a push) completes.
* progress, it suffices for any in-progress poll or new push on
* However, in the aggregate, we ensure at least probabilistic
* any empty queue to complete. (This is why we normally use
* non-blockingness. If an attempted steal fails, a thief always
* method pollAt and its variants that try once at the apparent
* chooses a different random victim target to try next. So, in
* base index, else consider alternative actions, rather than
* order for one thief to progress, it suffices for any
* method poll.)
* in-progress poll or new push on any empty queue to
* complete. (This is why we normally use method pollAt and its
* variants that try once at the apparent base index, else
* consider alternative actions, rather than method poll.)
*
*
* This approach also enables support of a user mode in which local
* This approach also enables support of a user mode in which local
* task processing is in FIFO, not LIFO order, simply by using
* task processing is in FIFO, not LIFO order, simply by using
...
@@ -334,37 +339,35 @@ public class ForkJoinPool extends AbstractExecutorService {
...
@@ -334,37 +339,35 @@ public class ForkJoinPool extends AbstractExecutorService {
* has not yet entered the wait queue. We solve this by requiring
* has not yet entered the wait queue. We solve this by requiring
* a full sweep of all workers (via repeated calls to method
* a full sweep of all workers (via repeated calls to method
* scan()) both before and after a newly waiting worker is added
* scan()) both before and after a newly waiting worker is added
* to the wait queue. During a rescan, the worker might release
* to the wait queue. Because enqueued workers may actually be
* some other queued worker rather than itself, which has the same
* rescanning rather than waiting, we set and clear the "parker"
* net effect. Because enqueued workers may actually be rescanning
* field of WorkQueues to reduce unnecessary calls to unpark.
* rather than waiting, we set and clear the "parker" field of
* (This requires a secondary recheck to avoid missed signals.)
* WorkQueues to reduce unnecessary calls to unpark. (This
* Note the unusual conventions about Thread.interrupts
* requires a secondary recheck to avoid missed signals.) Note
* surrounding parking and other blocking: Because interrupts are
* the unusual conventions about Thread.interrupts surrounding
* used solely to alert threads to check termination, which is
* parking and other blocking: Because interrupts are used solely
* checked anyway upon blocking, we clear status (using
* to alert threads to check termination, which is checked anyway
* Thread.interrupted) before any call to park, so that park does
* upon blocking, we clear status (using Thread.interrupted)
* not immediately return due to status being set via some other
* before any call to park, so that park does not immediately
* unrelated call to interrupt in user code.
* return due to status being set via some other unrelated call to
* interrupt in user code.
*
*
* Signalling. We create or wake up workers only when there
* Signalling. We create or wake up workers only when there
* appears to be at least one task they might be able to find and
* appears to be at least one task they might be able to find and
* execute. However, many other threads may notice the same task
* execute. When a submission is added or another worker adds a
* and each signal to wake up a thread that might take it. So in
* task to a queue that has fewer than two tasks, they signal
* general, pools will be over-signalled. When a submission is
* waiting workers (or trigger creation of new ones if fewer than
* added or another worker adds a task to a queue that has fewer
* the given parallelism level -- signalWork). These primary
* than two tasks, they signal waiting workers (or trigger
* signals are buttressed by others whenever other threads remove
* creation of new ones if fewer than the given parallelism level
* a task from a queue and notice that there are other tasks there
* -- signalWork), and may leave a hint to the unparked worker to
* as well. So in general, pools will be over-signalled. On most
* help signal others upon wakeup). These primary signals are
* platforms, signalling (unpark) overhead time is noticeably
* buttressed by others (see method helpSignal) whenever other
* threads scan for work or do not have a task to process. On
* most platforms, signalling (unpark) overhead time is noticeably
* long, and the time between signalling a thread and it actually
* long, and the time between signalling a thread and it actually
* making progress can be very noticeably long, so it is worth
* making progress can be very noticeably long, so it is worth
* offloading these delays from critical paths as much as
* offloading these delays from critical paths as much as
* possible.
* possible. Additionally, workers spin-down gradually, by staying
* alive so long as they see the ctl state changing. Similar
* stability-sensing techniques are also used before blocking in
* awaitJoin and helpComplete.
*
*
* Trimming workers. To release resources after periods of lack of
* Trimming workers. To release resources after periods of lack of
* use, a worker starting to wait when the pool is quiescent will
* use, a worker starting to wait when the pool is quiescent will
...
@@ -477,7 +480,7 @@ public class ForkJoinPool extends AbstractExecutorService {
...
@@ -477,7 +480,7 @@ public class ForkJoinPool extends AbstractExecutorService {
* Common Pool
* Common Pool
* ===========
* ===========
*
*
* The static common
P
ool always exists after static
* The static common
p
ool always exists after static
* initialization. Since it (or any other created pool) need
* initialization. Since it (or any other created pool) need
* never be used, we minimize initial construction overhead and
* never be used, we minimize initial construction overhead and
* footprint to the setup of about a dozen fields, with no nested
* footprint to the setup of about a dozen fields, with no nested
...
@@ -485,8 +488,11 @@ public class ForkJoinPool extends AbstractExecutorService {
...
@@ -485,8 +488,11 @@ public class ForkJoinPool extends AbstractExecutorService {
* fullExternalPush during the first submission to the pool.
* fullExternalPush during the first submission to the pool.
*
*
* When external threads submit to the common pool, they can
* When external threads submit to the common pool, they can
* perform some subtask processing (see externalHelpJoin and
* perform subtask processing (see externalHelpJoin and related
* related methods). We do not need to record whether these
* methods). This caller-helps policy makes it sensible to set
* common pool parallelism level to one (or more) less than the
* total number of available cores, or even zero for pure
* caller-runs. We do not need to record whether external
* submissions are to the common pool -- if not, externalHelpJoin
* submissions are to the common pool -- if not, externalHelpJoin
* returns quickly (at the most helping to signal some common pool
* returns quickly (at the most helping to signal some common pool
* workers). These submitters would otherwise be blocked waiting
* workers). These submitters would otherwise be blocked waiting
...
@@ -631,18 +637,10 @@ public class ForkJoinPool extends AbstractExecutorService {
...
@@ -631,18 +637,10 @@ public class ForkJoinPool extends AbstractExecutorService {
* do not want multiple WorkQueue instances or multiple queue
* do not want multiple WorkQueue instances or multiple queue
* arrays sharing cache lines. (It would be best for queue objects
* arrays sharing cache lines. (It would be best for queue objects
* and their arrays to share, but there is nothing available to
* and their arrays to share, but there is nothing available to
* help arrange that). Unfortunately, because they are recorded
* help arrange that). The @Contended annotation alerts JVMs to
* in a common array, WorkQueue instances are often moved to be
* try to keep instances apart.
* adjacent by garbage collectors. To reduce impact, we use field
* padding that works OK on common platforms; this effectively
* trades off slightly slower average field access for the sake of
* avoiding really bad worst-case access. (Until better JVM
* support is in place, this padding is dependent on transient
* properties of JVM field layout rules.) We also take care in
* allocating, sizing and resizing the array. Non-shared queue
* arrays are initialized by workers before use. Others are
* allocated on first use.
*/
*/
@sun
.
misc
.
Contended
static
final
class
WorkQueue
{
static
final
class
WorkQueue
{
/**
/**
* Capacity of work-stealing queue array upon initialization.
* Capacity of work-stealing queue array upon initialization.
...
@@ -664,16 +662,12 @@ public class ForkJoinPool extends AbstractExecutorService {
...
@@ -664,16 +662,12 @@ public class ForkJoinPool extends AbstractExecutorService {
*/
*/
static
final
int
MAXIMUM_QUEUE_CAPACITY
=
1
<<
26
;
// 64M
static
final
int
MAXIMUM_QUEUE_CAPACITY
=
1
<<
26
;
// 64M
// Heuristic padding to ameliorate unfortunate memory placements
volatile
long
pad00
,
pad01
,
pad02
,
pad03
,
pad04
,
pad05
,
pad06
;
int
seed
;
// for random scanning; initialize nonzero
volatile
int
eventCount
;
// encoded inactivation count; < 0 if inactive
volatile
int
eventCount
;
// encoded inactivation count; < 0 if inactive
int
nextWait
;
// encoded record of next event waiter
int
nextWait
;
// encoded record of next event waiter
int
hint
;
// steal or signal hint (index)
int
poolIndex
;
// index of this queue in pool (or 0)
final
int
mode
;
// 0: lifo, > 0: fifo, < 0: shared
int
nsteals
;
// number of steals
int
nsteals
;
// number of steals
int
hint
;
// steal index hint
short
poolIndex
;
// index of this queue in pool
final
short
mode
;
// 0: lifo, > 0: fifo, < 0: shared
volatile
int
qlock
;
// 1: locked, -1: terminate; else 0
volatile
int
qlock
;
// 1: locked, -1: terminate; else 0
volatile
int
base
;
// index of next slot for poll
volatile
int
base
;
// index of next slot for poll
int
top
;
// index of next slot for push
int
top
;
// index of next slot for push
...
@@ -684,15 +678,12 @@ public class ForkJoinPool extends AbstractExecutorService {
...
@@ -684,15 +678,12 @@ public class ForkJoinPool extends AbstractExecutorService {
volatile
ForkJoinTask
<?>
currentJoin
;
// task being joined in awaitJoin
volatile
ForkJoinTask
<?>
currentJoin
;
// task being joined in awaitJoin
ForkJoinTask
<?>
currentSteal
;
// current non-local task being executed
ForkJoinTask
<?>
currentSteal
;
// current non-local task being executed
volatile
Object
pad10
,
pad11
,
pad12
,
pad13
,
pad14
,
pad15
,
pad16
,
pad17
;
volatile
Object
pad18
,
pad19
,
pad1a
,
pad1b
,
pad1c
,
pad1d
;
WorkQueue
(
ForkJoinPool
pool
,
ForkJoinWorkerThread
owner
,
int
mode
,
WorkQueue
(
ForkJoinPool
pool
,
ForkJoinWorkerThread
owner
,
int
mode
,
int
seed
)
{
int
seed
)
{
this
.
pool
=
pool
;
this
.
pool
=
pool
;
this
.
owner
=
owner
;
this
.
owner
=
owner
;
this
.
mode
=
mode
;
this
.
mode
=
(
short
)
mode
;
this
.
seed
=
seed
;
this
.
hint
=
seed
;
// store initial seed for runWorker
// Place indices in the center of array (that is not yet allocated)
// Place indices in the center of array (that is not yet allocated)
base
=
top
=
INITIAL_QUEUE_CAPACITY
>>>
1
;
base
=
top
=
INITIAL_QUEUE_CAPACITY
>>>
1
;
}
}
...
@@ -705,7 +696,7 @@ public class ForkJoinPool extends AbstractExecutorService {
...
@@ -705,7 +696,7 @@ public class ForkJoinPool extends AbstractExecutorService {
return
(
n
>=
0
)
?
0
:
-
n
;
// ignore transient negative
return
(
n
>=
0
)
?
0
:
-
n
;
// ignore transient negative
}
}
/**
/**
* Provides a more accurate estimate of whether this queue has
* Provides a more accurate estimate of whether this queue has
* any tasks than does queueSize, by checking whether a
* any tasks than does queueSize, by checking whether a
* near-empty queue has at least one unclaimed task.
* near-empty queue has at least one unclaimed task.
...
@@ -730,20 +721,18 @@ public class ForkJoinPool extends AbstractExecutorService {
...
@@ -730,20 +721,18 @@ public class ForkJoinPool extends AbstractExecutorService {
*/
*/
final
void
push
(
ForkJoinTask
<?>
task
)
{
final
void
push
(
ForkJoinTask
<?>
task
)
{
ForkJoinTask
<?>[]
a
;
ForkJoinPool
p
;
ForkJoinTask
<?>[]
a
;
ForkJoinPool
p
;
int
s
=
top
,
m
,
n
;
int
s
=
top
,
n
;
if
((
a
=
array
)
!=
null
)
{
// ignore if queue removed
if
((
a
=
array
)
!=
null
)
{
// ignore if queue removed
int
j
=
(((
m
=
a
.
length
-
1
)
&
s
)
<<
ASHIFT
)
+
ABASE
;
int
m
=
a
.
length
-
1
;
U
.
putOrderedObject
(
a
,
j
,
task
);
U
.
putOrderedObject
(
a
,
((
m
&
s
)
<<
ASHIFT
)
+
ABASE
,
task
);
if
((
n
=
(
top
=
s
+
1
)
-
base
)
<=
2
)
{
if
((
n
=
(
top
=
s
+
1
)
-
base
)
<=
2
)
if
((
p
=
pool
)
!=
null
)
(
p
=
pool
).
signalWork
(
p
.
workQueues
,
this
);
p
.
signalWork
(
this
);
}
else
if
(
n
>=
m
)
else
if
(
n
>=
m
)
growArray
();
growArray
();
}
}
}
}
/**
/**
* Initializes or doubles the capacity of array. Call either
* Initializes or doubles the capacity of array. Call either
* by owner or with lock held -- it is OK for base, but not
* by owner or with lock held -- it is OK for base, but not
* top, to move while resizings are in progress.
* top, to move while resizings are in progress.
...
@@ -801,9 +790,8 @@ public class ForkJoinPool extends AbstractExecutorService {
...
@@ -801,9 +790,8 @@ public class ForkJoinPool extends AbstractExecutorService {
if
((
a
=
array
)
!=
null
)
{
if
((
a
=
array
)
!=
null
)
{
int
j
=
(((
a
.
length
-
1
)
&
b
)
<<
ASHIFT
)
+
ABASE
;
int
j
=
(((
a
.
length
-
1
)
&
b
)
<<
ASHIFT
)
+
ABASE
;
if
((
t
=
(
ForkJoinTask
<?>)
U
.
getObjectVolatile
(
a
,
j
))
!=
null
&&
if
((
t
=
(
ForkJoinTask
<?>)
U
.
getObjectVolatile
(
a
,
j
))
!=
null
&&
base
==
b
&&
base
==
b
&&
U
.
compareAndSwapObject
(
a
,
j
,
t
,
null
))
{
U
.
compareAndSwapObject
(
a
,
j
,
t
,
null
))
{
U
.
putOrderedInt
(
this
,
QBASE
,
b
+
1
);
base
=
b
+
1
;
return
t
;
return
t
;
}
}
}
}
...
@@ -819,9 +807,8 @@ public class ForkJoinPool extends AbstractExecutorService {
...
@@ -819,9 +807,8 @@ public class ForkJoinPool extends AbstractExecutorService {
int
j
=
(((
a
.
length
-
1
)
&
b
)
<<
ASHIFT
)
+
ABASE
;
int
j
=
(((
a
.
length
-
1
)
&
b
)
<<
ASHIFT
)
+
ABASE
;
t
=
(
ForkJoinTask
<?>)
U
.
getObjectVolatile
(
a
,
j
);
t
=
(
ForkJoinTask
<?>)
U
.
getObjectVolatile
(
a
,
j
);
if
(
t
!=
null
)
{
if
(
t
!=
null
)
{
if
(
base
==
b
&&
if
(
U
.
compareAndSwapObject
(
a
,
j
,
t
,
null
))
{
U
.
compareAndSwapObject
(
a
,
j
,
t
,
null
))
{
U
.
putOrderedInt
(
this
,
QBASE
,
b
+
1
);
base
=
b
+
1
;
return
t
;
return
t
;
}
}
}
}
...
@@ -878,46 +865,40 @@ public class ForkJoinPool extends AbstractExecutorService {
...
@@ -878,46 +865,40 @@ public class ForkJoinPool extends AbstractExecutorService {
ForkJoinTask
.
cancelIgnoringExceptions
(
t
);
ForkJoinTask
.
cancelIgnoringExceptions
(
t
);
}
}
/**
* Computes next value for random probes. Scans don't require
* a very high quality generator, but also not a crummy one.
* Marsaglia xor-shift is cheap and works well enough. Note:
* This is manually inlined in its usages in ForkJoinPool to
* avoid writes inside busy scan loops.
*/
final
int
nextSeed
()
{
int
r
=
seed
;
r
^=
r
<<
13
;
r
^=
r
>>>
17
;
return
seed
=
r
^=
r
<<
5
;
}
// Specialized execution methods
// Specialized execution methods
/**
/**
* Po
p
s and runs tasks until empty.
* Po
ll
s and runs tasks until empty.
*/
*/
private
void
popAndExecAll
()
{
final
void
pollAndExecAll
()
{
// A bit faster than repeated pop calls
for
(
ForkJoinTask
<?>
t
;
(
t
=
poll
())
!=
null
;)
ForkJoinTask
<?>[]
a
;
int
m
,
s
;
long
j
;
ForkJoinTask
<?>
t
;
t
.
doExec
();
while
((
a
=
array
)
!=
null
&&
(
m
=
a
.
length
-
1
)
>=
0
&&
(
s
=
top
-
1
)
-
base
>=
0
&&
(
t
=
((
ForkJoinTask
<?>)
U
.
getObject
(
a
,
j
=
((
m
&
s
)
<<
ASHIFT
)
+
ABASE
)))
!=
null
)
{
if
(
U
.
compareAndSwapObject
(
a
,
j
,
t
,
null
))
{
top
=
s
;
t
.
doExec
();
}
}
}
}
/**
/**
* Polls and runs tasks until empty.
* Executes a top-level task and any local tasks remaining
* after execution.
*/
*/
private
void
pollAndExecAll
()
{
final
void
runTask
(
ForkJoinTask
<?>
task
)
{
for
(
ForkJoinTask
<?>
t
;
(
t
=
poll
())
!=
null
;)
if
((
currentSteal
=
task
)
!=
null
)
{
t
.
doExec
();
task
.
doExec
();
ForkJoinTask
<?>[]
a
=
array
;
int
md
=
mode
;
++
nsteals
;
currentSteal
=
null
;
if
(
md
!=
0
)
pollAndExecAll
();
else
if
(
a
!=
null
)
{
int
s
,
m
=
a
.
length
-
1
;
ForkJoinTask
<?>
t
;
while
((
s
=
top
-
1
)
-
base
>=
0
&&
(
t
=
(
ForkJoinTask
<?>)
U
.
getAndSetObject
(
a
,
((
m
&
s
)
<<
ASHIFT
)
+
ABASE
,
null
))
!=
null
)
{
top
=
s
;
t
.
doExec
();
}
}
}
}
}
/**
/**
...
@@ -928,13 +909,15 @@ public class ForkJoinPool extends AbstractExecutorService {
...
@@ -928,13 +909,15 @@ public class ForkJoinPool extends AbstractExecutorService {
* @return false if no progress can be made, else true
* @return false if no progress can be made, else true
*/
*/
final
boolean
tryRemoveAndExec
(
ForkJoinTask
<?>
task
)
{
final
boolean
tryRemoveAndExec
(
ForkJoinTask
<?>
task
)
{
boolean
stat
=
true
,
removed
=
false
,
empty
=
true
;
boolean
stat
;
ForkJoinTask
<?>[]
a
;
int
m
,
s
,
b
,
n
;
ForkJoinTask
<?>[]
a
;
int
m
,
s
,
b
,
n
;
if
((
a
=
array
)
!=
null
&&
(
m
=
a
.
length
-
1
)
>=
0
&&
if
(
task
!=
null
&&
(
a
=
array
)
!=
null
&&
(
m
=
a
.
length
-
1
)
>=
0
&&
(
n
=
(
s
=
top
)
-
(
b
=
base
))
>
0
)
{
(
n
=
(
s
=
top
)
-
(
b
=
base
))
>
0
)
{
boolean
removed
=
false
,
empty
=
true
;
stat
=
true
;
for
(
ForkJoinTask
<?>
t
;;)
{
// traverse from s to b
for
(
ForkJoinTask
<?>
t
;;)
{
// traverse from s to b
int
j
=
((--
s
&
m
)
<<
ASHIFT
)
+
ABASE
;
long
j
=
((--
s
&
m
)
<<
ASHIFT
)
+
ABASE
;
t
=
(
ForkJoinTask
<?>)
U
.
getObject
Volatile
(
a
,
j
);
t
=
(
ForkJoinTask
<?>)
U
.
getObject
(
a
,
j
);
if
(
t
==
null
)
// inconsistent length
if
(
t
==
null
)
// inconsistent length
break
;
break
;
else
if
(
t
==
task
)
{
else
if
(
t
==
task
)
{
...
@@ -962,68 +945,95 @@ public class ForkJoinPool extends AbstractExecutorService {
...
@@ -962,68 +945,95 @@ public class ForkJoinPool extends AbstractExecutorService {
break
;
break
;
}
}
}
}
if
(
removed
)
task
.
doExec
();
}
}
if
(
removed
)
else
task
.
doExec
()
;
stat
=
false
;
return
stat
;
return
stat
;
}
}
/**
/**
*
Polls for and executes the given task or any other task in
*
Tries to poll for and execute the given task or any other
* its CountedCompleter computation.
*
task in
its CountedCompleter computation.
*/
*/
final
boolean
pollAndExecCC
(
ForkJoinTask
<?>
root
)
{
final
boolean
pollAndExecCC
(
CountedCompleter
<?>
root
)
{
ForkJoinTask
<?>[]
a
;
int
b
;
Object
o
;
ForkJoinTask
<?>[]
a
;
int
b
;
Object
o
;
CountedCompleter
<?>
t
,
r
;
outer:
while
((
b
=
base
)
-
top
<
0
&&
(
a
=
array
)
!=
null
)
{
if
((
b
=
base
)
-
top
<
0
&&
(
a
=
array
)
!=
null
)
{
long
j
=
(((
a
.
length
-
1
)
&
b
)
<<
ASHIFT
)
+
ABASE
;
long
j
=
(((
a
.
length
-
1
)
&
b
)
<<
ASHIFT
)
+
ABASE
;
if
((
o
=
U
.
getObject
(
a
,
j
))
==
null
||
if
((
o
=
U
.
getObjectVolatile
(
a
,
j
))
==
null
)
!(
o
instanceof
CountedCompleter
))
return
true
;
// retry
break
;
if
(
o
instanceof
CountedCompleter
)
{
for
(
CountedCompleter
<?>
t
=
(
CountedCompleter
<?>)
o
,
r
=
t
;;)
{
for
(
t
=
(
CountedCompleter
<?>)
o
,
r
=
t
;;)
{
if
(
r
==
root
)
{
if
(
r
==
root
)
{
if
(
base
==
b
&&
if
(
base
==
b
&&
U
.
compareAndSwapObject
(
a
,
j
,
t
,
null
))
{
U
.
compareAndSwapObject
(
a
,
j
,
t
,
null
))
{
base
=
b
+
1
;
U
.
putOrderedInt
(
this
,
QBASE
,
b
+
1
);
t
.
doExec
();
t
.
doExec
();
}
return
true
;
return
true
;
}
}
else
else
if
((
r
=
r
.
completer
)
==
null
)
break
;
//
restart
break
;
//
not part of root computation
}
}
if
((
r
=
r
.
completer
)
==
null
)
break
outer
;
// not part of root computation
}
}
}
}
return
false
;
return
false
;
}
}
/**
/**
*
Executes a top-level task and any local tasks remaining
*
Tries to pop and execute the given task or any other task
*
after execu
tion.
*
in its CountedCompleter computa
tion.
*/
*/
final
void
runTask
(
ForkJoinTask
<?>
t
)
{
final
boolean
externalPopAndExecCC
(
CountedCompleter
<?>
root
)
{
if
(
t
!=
null
)
{
ForkJoinTask
<?>[]
a
;
int
s
;
Object
o
;
CountedCompleter
<?>
t
,
r
;
(
currentSteal
=
t
).
doExec
();
if
(
base
-
(
s
=
top
)
<
0
&&
(
a
=
array
)
!=
null
)
{
currentSteal
=
null
;
long
j
=
(((
a
.
length
-
1
)
&
(
s
-
1
))
<<
ASHIFT
)
+
ABASE
;
++
nsteals
;
if
((
o
=
U
.
getObject
(
a
,
j
))
instanceof
CountedCompleter
)
{
if
(
base
-
top
<
0
)
{
// process remaining local tasks
for
(
t
=
(
CountedCompleter
<?>)
o
,
r
=
t
;;)
{
if
(
mode
==
0
)
if
(
r
==
root
)
{
popAndExecAll
();
if
(
U
.
compareAndSwapInt
(
this
,
QLOCK
,
0
,
1
))
{
else
if
(
top
==
s
&&
array
==
a
&&
pollAndExecAll
();
U
.
compareAndSwapObject
(
a
,
j
,
t
,
null
))
{
top
=
s
-
1
;
qlock
=
0
;
t
.
doExec
();
}
else
qlock
=
0
;
}
return
true
;
}
else
if
((
r
=
r
.
completer
)
==
null
)
break
;
}
}
}
}
}
return
false
;
}
}
/**
/**
*
Executes a non-top-level (stolen) task.
*
Internal version
*/
*/
final
void
runSubtask
(
ForkJoinTask
<?>
t
)
{
final
boolean
internalPopAndExecCC
(
CountedCompleter
<?>
root
)
{
if
(
t
!=
null
)
{
ForkJoinTask
<?>[]
a
;
int
s
;
Object
o
;
CountedCompleter
<?>
t
,
r
;
ForkJoinTask
<?>
ps
=
currentSteal
;
if
(
base
-
(
s
=
top
)
<
0
&&
(
a
=
array
)
!=
null
)
{
(
currentSteal
=
t
).
doExec
();
long
j
=
(((
a
.
length
-
1
)
&
(
s
-
1
))
<<
ASHIFT
)
+
ABASE
;
currentSteal
=
ps
;
if
((
o
=
U
.
getObject
(
a
,
j
))
instanceof
CountedCompleter
)
{
for
(
t
=
(
CountedCompleter
<?>)
o
,
r
=
t
;;)
{
if
(
r
==
root
)
{
if
(
U
.
compareAndSwapObject
(
a
,
j
,
t
,
null
))
{
top
=
s
-
1
;
t
.
doExec
();
}
return
true
;
}
else
if
((
r
=
r
.
completer
)
==
null
)
break
;
}
}
}
}
return
false
;
}
}
/**
/**
...
@@ -1040,6 +1050,7 @@ public class ForkJoinPool extends AbstractExecutorService {
...
@@ -1040,6 +1050,7 @@ public class ForkJoinPool extends AbstractExecutorService {
// Unsafe mechanics
// Unsafe mechanics
private
static
final
sun
.
misc
.
Unsafe
U
;
private
static
final
sun
.
misc
.
Unsafe
U
;
private
static
final
long
QBASE
;
private
static
final
long
QLOCK
;
private
static
final
long
QLOCK
;
private
static
final
int
ABASE
;
private
static
final
int
ABASE
;
private
static
final
int
ASHIFT
;
private
static
final
int
ASHIFT
;
...
@@ -1048,6 +1059,8 @@ public class ForkJoinPool extends AbstractExecutorService {
...
@@ -1048,6 +1059,8 @@ public class ForkJoinPool extends AbstractExecutorService {
U
=
sun
.
misc
.
Unsafe
.
getUnsafe
();
U
=
sun
.
misc
.
Unsafe
.
getUnsafe
();
Class
<?>
k
=
WorkQueue
.
class
;
Class
<?>
k
=
WorkQueue
.
class
;
Class
<?>
ak
=
ForkJoinTask
[].
class
;
Class
<?>
ak
=
ForkJoinTask
[].
class
;
QBASE
=
U
.
objectFieldOffset
(
k
.
getDeclaredField
(
"base"
));
QLOCK
=
U
.
objectFieldOffset
QLOCK
=
U
.
objectFieldOffset
(
k
.
getDeclaredField
(
"qlock"
));
(
k
.
getDeclaredField
(
"qlock"
));
ABASE
=
U
.
arrayBaseOffset
(
ak
);
ABASE
=
U
.
arrayBaseOffset
(
ak
);
...
@@ -1087,7 +1100,7 @@ public class ForkJoinPool extends AbstractExecutorService {
...
@@ -1087,7 +1100,7 @@ public class ForkJoinPool extends AbstractExecutorService {
/**
/**
* Common pool parallelism. To allow simpler use and management
* Common pool parallelism. To allow simpler use and management
* when common pool threads are disabled, we allow the underlying
* when common pool threads are disabled, we allow the underlying
* common.
config
field to be zero, but in that case still report
* common.
parallelism
field to be zero, but in that case still report
* parallelism as 1 to reflect resulting caller-runs mechanics.
* parallelism as 1 to reflect resulting caller-runs mechanics.
*/
*/
static
final
int
commonParallelism
;
static
final
int
commonParallelism
;
...
@@ -1227,35 +1240,18 @@ public class ForkJoinPool extends AbstractExecutorService {
...
@@ -1227,35 +1240,18 @@ public class ForkJoinPool extends AbstractExecutorService {
static
final
int
FIFO_QUEUE
=
1
;
static
final
int
FIFO_QUEUE
=
1
;
static
final
int
SHARED_QUEUE
=
-
1
;
static
final
int
SHARED_QUEUE
=
-
1
;
// bounds for #steps in scan loop -- must be power 2 minus 1
private
static
final
int
MIN_SCAN
=
0x1ff
;
// cover estimation slop
private
static
final
int
MAX_SCAN
=
0x1ffff
;
// 4 * max workers
// Instance fields
// Instance fields
/*
* Field layout of this class tends to matter more than one would
* like. Runtime layout order is only loosely related to
* declaration order and may differ across JVMs, but the following
* empirically works OK on current JVMs.
*/
// Heuristic padding to ameliorate unfortunate memory placements
volatile
long
pad00
,
pad01
,
pad02
,
pad03
,
pad04
,
pad05
,
pad06
;
volatile
long
stealCount
;
// collects worker counts
volatile
long
stealCount
;
// collects worker counts
volatile
long
ctl
;
// main pool control
volatile
long
ctl
;
// main pool control
volatile
int
plock
;
// shutdown status and seqLock
volatile
int
plock
;
// shutdown status and seqLock
volatile
int
indexSeed
;
// worker/submitter index seed
volatile
int
indexSeed
;
// worker/submitter index seed
final
int
config
;
// mode and parallelism level
final
short
parallelism
;
// parallelism level
final
short
mode
;
// LIFO/FIFO
WorkQueue
[]
workQueues
;
// main registry
WorkQueue
[]
workQueues
;
// main registry
final
ForkJoinWorkerThreadFactory
factory
;
final
ForkJoinWorkerThreadFactory
factory
;
final
UncaughtExceptionHandler
ueh
;
// per-worker UEH
final
UncaughtExceptionHandler
ueh
;
// per-worker UEH
final
String
workerNamePrefix
;
// to create worker name string
final
String
workerNamePrefix
;
// to create worker name string
volatile
Object
pad10
,
pad11
,
pad12
,
pad13
,
pad14
,
pad15
,
pad16
,
pad17
;
volatile
Object
pad18
,
pad19
,
pad1a
,
pad1b
;
/**
/**
* Acquires the plock lock to protect worker array and related
* Acquires the plock lock to protect worker array and related
* updates. This method is called only if an initial CAS on plock
* updates. This method is called only if an initial CAS on plock
...
@@ -1307,11 +1303,11 @@ public class ForkJoinPool extends AbstractExecutorService {
...
@@ -1307,11 +1303,11 @@ public class ForkJoinPool extends AbstractExecutorService {
* parallelism level exist. Adjusts counts etc on failure.
* parallelism level exist. Adjusts counts etc on failure.
*/
*/
private
void
tryAddWorker
()
{
private
void
tryAddWorker
()
{
long
c
;
int
u
;
long
c
;
int
u
,
e
;
while
((
u
=
(
int
)((
c
=
ctl
)
>>>
32
))
<
0
&&
while
((
u
=
(
int
)((
c
=
ctl
)
>>>
32
))
<
0
&&
(
u
&
SHORT_SIGN
)
!=
0
&&
(
int
)
c
=
=
0
)
{
(
u
&
SHORT_SIGN
)
!=
0
&&
(
e
=
(
int
)
c
)
>
=
0
)
{
long
nc
=
(
long
)(((
u
+
UTC_UNIT
)
&
UTC_MASK
)
|
long
nc
=
(
(
long
)(((
u
+
UTC_UNIT
)
&
UTC_MASK
)
|
((
u
+
UAC_UNIT
)
&
UAC_MASK
))
<<
32
;
((
u
+
UAC_UNIT
)
&
UAC_MASK
))
<<
32
)
|
(
long
)
e
;
if
(
U
.
compareAndSwapLong
(
this
,
CTL
,
c
,
nc
))
{
if
(
U
.
compareAndSwapLong
(
this
,
CTL
,
c
,
nc
))
{
ForkJoinWorkerThreadFactory
fac
;
ForkJoinWorkerThreadFactory
fac
;
Throwable
ex
=
null
;
Throwable
ex
=
null
;
...
@@ -1322,8 +1318,8 @@ public class ForkJoinPool extends AbstractExecutorService {
...
@@ -1322,8 +1318,8 @@ public class ForkJoinPool extends AbstractExecutorService {
wt
.
start
();
wt
.
start
();
break
;
break
;
}
}
}
catch
(
Throwable
e
)
{
}
catch
(
Throwable
rex
)
{
ex
=
e
;
ex
=
rex
;
}
}
deregisterWorker
(
wt
,
ex
);
deregisterWorker
(
wt
,
ex
);
break
;
break
;
...
@@ -1351,7 +1347,7 @@ public class ForkJoinPool extends AbstractExecutorService {
...
@@ -1351,7 +1347,7 @@ public class ForkJoinPool extends AbstractExecutorService {
do
{}
while
(!
U
.
compareAndSwapInt
(
this
,
INDEXSEED
,
s
=
indexSeed
,
do
{}
while
(!
U
.
compareAndSwapInt
(
this
,
INDEXSEED
,
s
=
indexSeed
,
s
+=
SEED_INCREMENT
)
||
s
+=
SEED_INCREMENT
)
||
s
==
0
);
// skip 0
s
==
0
);
// skip 0
WorkQueue
w
=
new
WorkQueue
(
this
,
wt
,
config
>>>
16
,
s
);
WorkQueue
w
=
new
WorkQueue
(
this
,
wt
,
mode
,
s
);
if
(((
ps
=
plock
)
&
PL_LOCK
)
!=
0
||
if
(((
ps
=
plock
)
&
PL_LOCK
)
!=
0
||
!
U
.
compareAndSwapInt
(
this
,
PLOCK
,
ps
,
ps
+=
PL_LOCK
))
!
U
.
compareAndSwapInt
(
this
,
PLOCK
,
ps
,
ps
+=
PL_LOCK
))
ps
=
acquirePlock
();
ps
=
acquirePlock
();
...
@@ -1371,14 +1367,15 @@ public class ForkJoinPool extends AbstractExecutorService {
...
@@ -1371,14 +1367,15 @@ public class ForkJoinPool extends AbstractExecutorService {
}
}
}
}
}
}
w
.
eventCount
=
w
.
poolIndex
=
r
;
// volatile write orders
w
.
poolIndex
=
(
short
)
r
;
w
.
eventCount
=
r
;
// volatile write orders
ws
[
r
]
=
w
;
ws
[
r
]
=
w
;
}
}
}
finally
{
}
finally
{
if
(!
U
.
compareAndSwapInt
(
this
,
PLOCK
,
ps
,
nps
))
if
(!
U
.
compareAndSwapInt
(
this
,
PLOCK
,
ps
,
nps
))
releasePlock
(
nps
);
releasePlock
(
nps
);
}
}
wt
.
setName
(
workerNamePrefix
.
concat
(
Integer
.
toString
(
w
.
poolIndex
)));
wt
.
setName
(
workerNamePrefix
.
concat
(
Integer
.
toString
(
w
.
poolIndex
>>>
1
)));
return
w
;
return
w
;
}
}
...
@@ -1396,9 +1393,7 @@ public class ForkJoinPool extends AbstractExecutorService {
...
@@ -1396,9 +1393,7 @@ public class ForkJoinPool extends AbstractExecutorService {
if
(
wt
!=
null
&&
(
w
=
wt
.
workQueue
)
!=
null
)
{
if
(
wt
!=
null
&&
(
w
=
wt
.
workQueue
)
!=
null
)
{
int
ps
;
int
ps
;
w
.
qlock
=
-
1
;
// ensure set
w
.
qlock
=
-
1
;
// ensure set
long
ns
=
w
.
nsteals
,
sc
;
// collect steal count
U
.
getAndAddLong
(
this
,
STEALCOUNT
,
w
.
nsteals
);
// collect steals
do
{}
while
(!
U
.
compareAndSwapLong
(
this
,
STEALCOUNT
,
sc
=
stealCount
,
sc
+
ns
));
if
(((
ps
=
plock
)
&
PL_LOCK
)
!=
0
||
if
(((
ps
=
plock
)
&
PL_LOCK
)
!=
0
||
!
U
.
compareAndSwapInt
(
this
,
PLOCK
,
ps
,
ps
+=
PL_LOCK
))
!
U
.
compareAndSwapInt
(
this
,
PLOCK
,
ps
,
ps
+=
PL_LOCK
))
ps
=
acquirePlock
();
ps
=
acquirePlock
();
...
@@ -1464,19 +1459,21 @@ public class ForkJoinPool extends AbstractExecutorService {
...
@@ -1464,19 +1459,21 @@ public class ForkJoinPool extends AbstractExecutorService {
* @param task the task. Caller must ensure non-null.
* @param task the task. Caller must ensure non-null.
*/
*/
final
void
externalPush
(
ForkJoinTask
<?>
task
)
{
final
void
externalPush
(
ForkJoinTask
<?>
task
)
{
WorkQueue
[]
ws
;
WorkQueue
q
;
int
z
,
m
;
ForkJoinTask
<?>[]
a
;
WorkQueue
q
;
int
m
,
s
,
n
,
am
;
ForkJoinTask
<?>[]
a
;
if
((
z
=
ThreadLocalRandom
.
getProbe
())
!=
0
&&
plock
>
0
&&
int
r
=
ThreadLocalRandom
.
getProbe
();
(
ws
=
workQueues
)
!=
null
&&
(
m
=
(
ws
.
length
-
1
))
>=
0
&&
int
ps
=
plock
;
(
q
=
ws
[
m
&
z
&
SQMASK
])
!=
null
&&
WorkQueue
[]
ws
=
workQueues
;
if
(
ps
>
0
&&
ws
!=
null
&&
(
m
=
(
ws
.
length
-
1
))
>=
0
&&
(
q
=
ws
[
m
&
r
&
SQMASK
])
!=
null
&&
r
!=
0
&&
U
.
compareAndSwapInt
(
q
,
QLOCK
,
0
,
1
))
{
// lock
U
.
compareAndSwapInt
(
q
,
QLOCK
,
0
,
1
))
{
// lock
i
nt
b
=
q
.
base
,
s
=
q
.
top
,
n
,
an
;
i
f
((
a
=
q
.
array
)
!=
null
&&
if
((
a
=
q
.
array
)
!=
null
&&
(
an
=
a
.
length
)
>
(
n
=
s
+
1
-
b
))
{
(
am
=
a
.
length
-
1
)
>
(
n
=
(
s
=
q
.
top
)
-
q
.
base
))
{
int
j
=
((
(
an
-
1
)
&
s
)
<<
ASHIFT
)
+
ABASE
;
int
j
=
((
am
&
s
)
<<
ASHIFT
)
+
ABASE
;
U
.
putOrderedObject
(
a
,
j
,
task
);
U
.
putOrderedObject
(
a
,
j
,
task
);
q
.
top
=
s
+
1
;
// push on to deque
q
.
top
=
s
+
1
;
// push on to deque
q
.
qlock
=
0
;
q
.
qlock
=
0
;
if
(
n
<=
2
)
if
(
n
<=
1
)
signalWork
(
q
);
signalWork
(
ws
,
q
);
return
;
return
;
}
}
q
.
qlock
=
0
;
q
.
qlock
=
0
;
...
@@ -1514,7 +1511,7 @@ public class ForkJoinPool extends AbstractExecutorService {
...
@@ -1514,7 +1511,7 @@ public class ForkJoinPool extends AbstractExecutorService {
throw
new
RejectedExecutionException
();
throw
new
RejectedExecutionException
();
else
if
(
ps
==
0
||
(
ws
=
workQueues
)
==
null
||
else
if
(
ps
==
0
||
(
ws
=
workQueues
)
==
null
||
(
m
=
ws
.
length
-
1
)
<
0
)
{
// initialize workQueues
(
m
=
ws
.
length
-
1
)
<
0
)
{
// initialize workQueues
int
p
=
config
&
SMASK
;
// find power of two table size
int
p
=
parallelism
;
// find power of two table size
int
n
=
(
p
>
1
)
?
p
-
1
:
1
;
// ensure at least 2 slots
int
n
=
(
p
>
1
)
?
p
-
1
:
1
;
// ensure at least 2 slots
n
|=
n
>>>
1
;
n
|=
n
>>>
2
;
n
|=
n
>>>
4
;
n
|=
n
>>>
1
;
n
|=
n
>>>
2
;
n
|=
n
>>>
4
;
n
|=
n
>>>
8
;
n
|=
n
>>>
16
;
n
=
(
n
+
1
)
<<
1
;
n
|=
n
>>>
8
;
n
|=
n
>>>
16
;
n
=
(
n
+
1
)
<<
1
;
...
@@ -1546,7 +1543,7 @@ public class ForkJoinPool extends AbstractExecutorService {
...
@@ -1546,7 +1543,7 @@ public class ForkJoinPool extends AbstractExecutorService {
q
.
qlock
=
0
;
// unlock
q
.
qlock
=
0
;
// unlock
}
}
if
(
submitted
)
{
if
(
submitted
)
{
signalWork
(
q
);
signalWork
(
ws
,
q
);
return
;
return
;
}
}
}
}
...
@@ -1554,6 +1551,7 @@ public class ForkJoinPool extends AbstractExecutorService {
...
@@ -1554,6 +1551,7 @@ public class ForkJoinPool extends AbstractExecutorService {
}
}
else
if
(((
ps
=
plock
)
&
PL_LOCK
)
==
0
)
{
// create new queue
else
if
(((
ps
=
plock
)
&
PL_LOCK
)
==
0
)
{
// create new queue
q
=
new
WorkQueue
(
this
,
null
,
SHARED_QUEUE
,
r
);
q
=
new
WorkQueue
(
this
,
null
,
SHARED_QUEUE
,
r
);
q
.
poolIndex
=
(
short
)
k
;
if
(((
ps
=
plock
)
&
PL_LOCK
)
!=
0
||
if
(((
ps
=
plock
)
&
PL_LOCK
)
!=
0
||
!
U
.
compareAndSwapInt
(
this
,
PLOCK
,
ps
,
ps
+=
PL_LOCK
))
!
U
.
compareAndSwapInt
(
this
,
PLOCK
,
ps
,
ps
+=
PL_LOCK
))
ps
=
acquirePlock
();
ps
=
acquirePlock
();
...
@@ -1577,41 +1575,42 @@ public class ForkJoinPool extends AbstractExecutorService {
...
@@ -1577,41 +1575,42 @@ public class ForkJoinPool extends AbstractExecutorService {
*/
*/
final
void
incrementActiveCount
()
{
final
void
incrementActiveCount
()
{
long
c
;
long
c
;
do
{}
while
(!
U
.
compareAndSwapLong
(
this
,
CTL
,
c
=
ctl
,
c
+
AC_UNIT
));
do
{}
while
(!
U
.
compareAndSwapLong
(
this
,
CTL
,
c
=
ctl
,
((
c
&
~
AC_MASK
)
|
((
c
&
AC_MASK
)
+
AC_UNIT
))));
}
}
/**
/**
* Tries to create or activate a worker if too few are active.
* Tries to create or activate a worker if too few are active.
*
*
* @param q the (non-null) queue holding tasks to be signalled
* @param ws the worker array to use to find signallees
* @param q if non-null, the queue holding tasks to be processed
*/
*/
final
void
signalWork
(
WorkQueue
q
)
{
final
void
signalWork
(
WorkQueue
[]
ws
,
WorkQueue
q
)
{
int
hint
=
q
.
poolIndex
;
for
(;;)
{
long
c
;
int
e
,
u
,
i
,
n
;
WorkQueue
[]
ws
;
WorkQueue
w
;
Thread
p
;
long
c
;
int
e
,
u
,
i
;
WorkQueue
w
;
Thread
p
;
while
((
u
=
(
int
)((
c
=
ctl
)
>>>
32
))
<
0
)
{
if
((
u
=
(
int
)((
c
=
ctl
)
>>>
32
))
>=
0
)
if
((
e
=
(
int
)
c
)
>
0
)
{
break
;
if
((
ws
=
workQueues
)
!=
null
&&
ws
.
length
>
(
i
=
e
&
SMASK
)
&&
if
((
e
=
(
int
)
c
)
<=
0
)
{
(
w
=
ws
[
i
])
!=
null
&&
w
.
eventCount
==
(
e
|
INT_SIGN
))
{
long
nc
=
(((
long
)(
w
.
nextWait
&
E_MASK
))
|
((
long
)(
u
+
UAC_UNIT
)
<<
32
));
if
(
U
.
compareAndSwapLong
(
this
,
CTL
,
c
,
nc
))
{
w
.
hint
=
hint
;
w
.
eventCount
=
(
e
+
E_SEQ
)
&
E_MASK
;
if
((
p
=
w
.
parker
)
!=
null
)
U
.
unpark
(
p
);
break
;
}
if
(
q
.
top
-
q
.
base
<=
0
)
break
;
}
else
break
;
}
else
{
if
((
short
)
u
<
0
)
if
((
short
)
u
<
0
)
tryAddWorker
();
tryAddWorker
();
break
;
break
;
}
}
if
(
ws
==
null
||
ws
.
length
<=
(
i
=
e
&
SMASK
)
||
(
w
=
ws
[
i
])
==
null
)
break
;
long
nc
=
(((
long
)(
w
.
nextWait
&
E_MASK
))
|
((
long
)(
u
+
UAC_UNIT
))
<<
32
);
int
ne
=
(
e
+
E_SEQ
)
&
E_MASK
;
if
(
w
.
eventCount
==
(
e
|
INT_SIGN
)
&&
U
.
compareAndSwapLong
(
this
,
CTL
,
c
,
nc
))
{
w
.
eventCount
=
ne
;
if
((
p
=
w
.
parker
)
!=
null
)
U
.
unpark
(
p
);
break
;
}
if
(
q
!=
null
&&
q
.
base
>=
q
.
top
)
break
;
}
}
}
}
...
@@ -1622,215 +1621,152 @@ public class ForkJoinPool extends AbstractExecutorService {
...
@@ -1622,215 +1621,152 @@ public class ForkJoinPool extends AbstractExecutorService {
*/
*/
final
void
runWorker
(
WorkQueue
w
)
{
final
void
runWorker
(
WorkQueue
w
)
{
w
.
growArray
();
// allocate queue
w
.
growArray
();
// allocate queue
do
{
w
.
runTask
(
scan
(
w
));
}
while
(
w
.
qlock
>=
0
);
for
(
int
r
=
w
.
hint
;
scan
(
w
,
r
)
==
0
;
)
{
r
^=
r
<<
13
;
r
^=
r
>>>
17
;
r
^=
r
<<
5
;
// xorshift
}
}
}
/**
/**
* Scans for and, if found, r
etur
ns one task, else possibly
* Scans for and, if found, r
u
ns one task, else possibly
* inactivates the worker. This method operates on single reads of
* inactivates the worker. This method operates on single reads of
* volatile state and is designed to be re-invoked continuously,
* volatile state and is designed to be re-invoked continuously,
* in part because it returns upon detecting inconsistencies,
* in part because it returns upon detecting inconsistencies,
* contention, or state changes that indicate possible success on
* contention, or state changes that indicate possible success on
* re-invocation.
* re-invocation.
*
*
* The scan searches for tasks across queues (starting at a random
* The scan searches for tasks across queues starting at a random
* index, and relying on registerWorker to irregularly scatter
* index, checking each at least twice. The scan terminates upon
* them within array to avoid bias), checking each at least twice.
* either finding a non-empty queue, or completing the sweep. If
* The scan terminates upon either finding a non-empty queue, or
* the worker is not inactivated, it takes and runs a task from
* completing the sweep. If the worker is not inactivated, it
* this queue. Otherwise, if not activated, it tries to activate
* takes and returns a task from this queue. Otherwise, if not
* itself or some other worker by signalling. On failure to find a
* activated, it signals workers (that may include itself) and
* task, returns (for retry) if pool state may have changed during
* returns so caller can retry. Also returns for true if the
* an empty scan, or tries to inactivate if active, else possibly
* worker array may have changed during an empty scan. On failure
* blocks or terminates via method awaitWork.
* to find a task, we take one of the following actions, after
* which the caller will retry calling this method unless
* terminated.
*
* * If pool is terminating, terminate the worker.
*
* * If not already enqueued, try to inactivate and enqueue the
* worker on wait queue. Or, if inactivating has caused the pool
* to be quiescent, relay to idleAwaitWork to possibly shrink
* pool.
*
* * If already enqueued and none of the above apply, possibly
* park awaiting signal, else lingering to help scan and signal.
*
* * If a non-empty queue discovered or left as a hint,
* help wake up other workers before return.
*
*
* @param w the worker (via its WorkQueue)
* @param w the worker (via its WorkQueue)
* @return a task or null if none found
* @param r a random seed
* @return worker qlock status if would have waited, else 0
*/
*/
private
final
ForkJoinTask
<?>
scan
(
WorkQueue
w
)
{
private
final
int
scan
(
WorkQueue
w
,
int
r
)
{
WorkQueue
[]
ws
;
int
m
;
WorkQueue
[]
ws
;
int
m
;
int
ps
=
plock
;
// read plock before ws
long
c
=
ctl
;
// for consistency check
if
(
w
!=
null
&&
(
ws
=
workQueues
)
!=
null
&&
(
m
=
ws
.
length
-
1
)
>=
0
)
{
if
((
ws
=
workQueues
)
!=
null
&&
(
m
=
ws
.
length
-
1
)
>=
0
&&
w
!=
null
)
{
int
ec
=
w
.
eventCount
;
// ec is negative if inactive
for
(
int
j
=
m
+
m
+
1
,
ec
=
w
.
eventCount
;;)
{
int
r
=
w
.
seed
;
r
^=
r
<<
13
;
r
^=
r
>>>
17
;
w
.
seed
=
r
^=
r
<<
5
;
WorkQueue
q
;
int
b
,
e
;
ForkJoinTask
<?>[]
a
;
ForkJoinTask
<?>
t
;
w
.
hint
=
-
1
;
// update seed and clear hint
if
((
q
=
ws
[(
r
-
j
)
&
m
])
!=
null
&&
int
j
=
((
m
+
m
+
1
)
|
MIN_SCAN
)
&
MAX_SCAN
;
(
b
=
q
.
base
)
-
q
.
top
<
0
&&
(
a
=
q
.
array
)
!=
null
)
{
do
{
long
i
=
(((
a
.
length
-
1
)
&
b
)
<<
ASHIFT
)
+
ABASE
;
WorkQueue
q
;
ForkJoinTask
<?>[]
a
;
int
b
;
if
((
t
=
((
ForkJoinTask
<?>)
if
((
q
=
ws
[(
r
+
j
)
&
m
])
!=
null
&&
(
b
=
q
.
base
)
-
q
.
top
<
0
&&
U
.
getObjectVolatile
(
a
,
i
)))
!=
null
)
{
(
a
=
q
.
array
)
!=
null
)
{
// probably nonempty
if
(
ec
<
0
)
int
i
=
(((
a
.
length
-
1
)
&
b
)
<<
ASHIFT
)
+
ABASE
;
helpRelease
(
c
,
ws
,
w
,
q
,
b
);
ForkJoinTask
<?>
t
=
(
ForkJoinTask
<?>)
else
if
(
q
.
base
==
b
&&
U
.
getObjectVolatile
(
a
,
i
);
U
.
compareAndSwapObject
(
a
,
i
,
t
,
null
))
{
if
(
q
.
base
==
b
&&
ec
>=
0
&&
t
!=
null
&&
U
.
putOrderedInt
(
q
,
QBASE
,
b
+
1
);
U
.
compareAndSwapObject
(
a
,
i
,
t
,
null
))
{
if
((
b
+
1
)
-
q
.
top
<
0
)
if
((
q
.
base
=
b
+
1
)
-
q
.
top
<
0
)
signalWork
(
ws
,
q
);
signalWork
(
q
);
w
.
runTask
(
t
);
return
t
;
// taken
}
}
else
if
((
ec
<
0
||
j
<
m
)
&&
(
int
)(
ctl
>>
AC_SHIFT
)
<=
0
)
{
w
.
hint
=
(
r
+
j
)
&
m
;
// help signal below
break
;
// cannot take
}
}
break
;
}
}
}
while
(--
j
>=
0
);
else
if
(--
j
<
0
)
{
if
((
ec
|
(
e
=
(
int
)
c
))
<
0
)
// inactive or terminating
int
h
,
e
,
ns
;
long
c
,
sc
;
WorkQueue
q
;
return
awaitWork
(
w
,
c
,
ec
);
if
((
ns
=
w
.
nsteals
)
!=
0
)
{
else
if
(
ctl
==
c
)
{
// try to inactivate and enqueue
if
(
U
.
compareAndSwapLong
(
this
,
STEALCOUNT
,
long
nc
=
(
long
)
ec
|
((
c
-
AC_UNIT
)
&
(
AC_MASK
|
TC_MASK
));
sc
=
stealCount
,
sc
+
ns
))
w
.
nextWait
=
e
;
w
.
nsteals
=
0
;
// collect steals and rescan
}
else
if
(
plock
!=
ps
)
// consistency check
;
// skip
else
if
((
e
=
(
int
)(
c
=
ctl
))
<
0
)
w
.
qlock
=
-
1
;
// pool is terminating
else
{
if
((
h
=
w
.
hint
)
<
0
)
{
if
(
ec
>=
0
)
{
// try to enqueue/inactivate
long
nc
=
(((
long
)
ec
|
((
c
-
AC_UNIT
)
&
(
AC_MASK
|
TC_MASK
))));
w
.
nextWait
=
e
;
// link and mark inactive
w
.
eventCount
=
ec
|
INT_SIGN
;
w
.
eventCount
=
ec
|
INT_SIGN
;
if
(
ctl
!=
c
||
!
U
.
compareAndSwapLong
(
this
,
CTL
,
c
,
nc
))
if
(!
U
.
compareAndSwapLong
(
this
,
CTL
,
c
,
nc
))
w
.
eventCount
=
ec
;
// unmark on CAS failure
w
.
eventCount
=
ec
;
// back out
else
if
((
int
)(
c
>>
AC_SHIFT
)
==
1
-
(
config
&
SMASK
))
idleAwaitWork
(
w
,
nc
,
c
);
}
else
if
(
w
.
eventCount
<
0
&&
ctl
==
c
)
{
Thread
wt
=
Thread
.
currentThread
();
Thread
.
interrupted
();
// clear status
U
.
putObject
(
wt
,
PARKBLOCKER
,
this
);
w
.
parker
=
wt
;
// emulate LockSupport.park
if
(
w
.
eventCount
<
0
)
// recheck
U
.
park
(
false
,
0L
);
// block
w
.
parker
=
null
;
U
.
putObject
(
wt
,
PARKBLOCKER
,
null
);
}
}
if
((
h
>=
0
||
(
h
=
w
.
hint
)
>=
0
)
&&
(
ws
=
workQueues
)
!=
null
&&
h
<
ws
.
length
&&
(
q
=
ws
[
h
])
!=
null
)
{
// signal others before retry
WorkQueue
v
;
Thread
p
;
int
u
,
i
,
s
;
for
(
int
n
=
(
config
&
SMASK
)
-
1
;;)
{
int
idleCount
=
(
w
.
eventCount
<
0
)
?
0
:
-
1
;
if
(((
s
=
idleCount
-
q
.
base
+
q
.
top
)
<=
n
&&
(
n
=
s
)
<=
0
)
||
(
u
=
(
int
)((
c
=
ctl
)
>>>
32
))
>=
0
||
(
e
=
(
int
)
c
)
<=
0
||
m
<
(
i
=
e
&
SMASK
)
||
(
v
=
ws
[
i
])
==
null
)
break
;
long
nc
=
(((
long
)(
v
.
nextWait
&
E_MASK
))
|
((
long
)(
u
+
UAC_UNIT
)
<<
32
));
if
(
v
.
eventCount
!=
(
e
|
INT_SIGN
)
||
!
U
.
compareAndSwapLong
(
this
,
CTL
,
c
,
nc
))
break
;
v
.
hint
=
h
;
v
.
eventCount
=
(
e
+
E_SEQ
)
&
E_MASK
;
if
((
p
=
v
.
parker
)
!=
null
)
U
.
unpark
(
p
);
if
(--
n
<=
0
)
break
;
}
}
break
;
}
}
}
}
}
}
return
null
;
return
0
;
}
}
/**
/**
* If inactivating worker w has caused the pool to become
* A continuation of scan(), possibly blocking or terminating
* quiescent, checks for pool termination, and, so long as this is
* worker w. Returns without blocking if pool state has apparently
* not the only worker, waits for event for up to a given
* changed since last invocation. Also, if inactivating w has
* duration. On timeout, if ctl has not changed, terminates the
* caused the pool to become quiescent, checks for pool
* worker, which will in turn wake up another worker to possibly
* termination, and, so long as this is not the only worker, waits
* repeat this process.
* for event for up to a given duration. On timeout, if ctl has
* not changed, terminates the worker, which will in turn wake up
* another worker to possibly repeat this process.
*
*
* @param w the calling worker
* @param w the calling worker
* @param currentCtl the ctl value triggering possible quiescence
* @param c the ctl value on entry to scan
* @param prevCtl the ctl value to restore if thread is terminated
* @param ec the worker's eventCount on entry to scan
*/
*/
private
void
idleAwaitWork
(
WorkQueue
w
,
long
currentCtl
,
long
prevCtl
)
{
private
final
int
awaitWork
(
WorkQueue
w
,
long
c
,
int
ec
)
{
if
(
w
!=
null
&&
w
.
eventCount
<
0
&&
int
stat
,
ns
;
long
parkTime
,
deadline
;
!
tryTerminate
(
false
,
false
)
&&
(
int
)
prevCtl
!=
0
&&
if
((
stat
=
w
.
qlock
)
>=
0
&&
w
.
eventCount
==
ec
&&
ctl
==
c
&&
ctl
==
currentCtl
)
{
!
Thread
.
interrupted
())
{
int
dc
=
-(
short
)(
currentCtl
>>>
TC_SHIFT
);
int
e
=
(
int
)
c
;
long
parkTime
=
dc
<
0
?
FAST_IDLE_TIMEOUT:
(
dc
+
1
)
*
IDLE_TIMEOUT
;
int
u
=
(
int
)(
c
>>>
32
);
long
deadline
=
System
.
nanoTime
()
+
parkTime
-
TIMEOUT_SLOP
;
int
d
=
(
u
>>
UAC_SHIFT
)
+
parallelism
;
// active count
Thread
wt
=
Thread
.
currentThread
();
while
(
ctl
==
currentCtl
)
{
if
(
e
<
0
||
(
d
<=
0
&&
tryTerminate
(
false
,
false
)))
Thread
.
interrupted
();
// timed variant of version in scan()
stat
=
w
.
qlock
=
-
1
;
// pool is terminating
U
.
putObject
(
wt
,
PARKBLOCKER
,
this
);
else
if
((
ns
=
w
.
nsteals
)
!=
0
)
{
// collect steals and retry
w
.
parker
=
wt
;
w
.
nsteals
=
0
;
if
(
ctl
==
currentCtl
)
U
.
getAndAddLong
(
this
,
STEALCOUNT
,
(
long
)
ns
);
U
.
park
(
false
,
parkTime
);
}
w
.
parker
=
null
;
else
{
U
.
putObject
(
wt
,
PARKBLOCKER
,
null
);
long
pc
=
((
d
>
0
||
ec
!=
(
e
|
INT_SIGN
))
?
0L
:
if
(
ctl
!=
currentCtl
)
((
long
)(
w
.
nextWait
&
E_MASK
))
|
// ctl to restore
break
;
((
long
)(
u
+
UAC_UNIT
))
<<
32
);
if
(
deadline
-
System
.
nanoTime
()
<=
0L
&&
if
(
pc
!=
0L
)
{
// timed wait if last waiter
U
.
compareAndSwapLong
(
this
,
CTL
,
currentCtl
,
prevCtl
))
{
int
dc
=
-(
short
)(
c
>>>
TC_SHIFT
);
w
.
eventCount
=
(
w
.
eventCount
+
E_SEQ
)
|
E_MASK
;
parkTime
=
(
dc
<
0
?
FAST_IDLE_TIMEOUT:
w
.
hint
=
-
1
;
(
dc
+
1
)
*
IDLE_TIMEOUT
);
w
.
qlock
=
-
1
;
// shrink
deadline
=
System
.
nanoTime
()
+
parkTime
-
TIMEOUT_SLOP
;
break
;
}
else
parkTime
=
deadline
=
0L
;
if
(
w
.
eventCount
==
ec
&&
ctl
==
c
)
{
Thread
wt
=
Thread
.
currentThread
();
U
.
putObject
(
wt
,
PARKBLOCKER
,
this
);
w
.
parker
=
wt
;
// emulate LockSupport.park
if
(
w
.
eventCount
==
ec
&&
ctl
==
c
)
U
.
park
(
false
,
parkTime
);
// must recheck before park
w
.
parker
=
null
;
U
.
putObject
(
wt
,
PARKBLOCKER
,
null
);
if
(
parkTime
!=
0L
&&
ctl
==
c
&&
deadline
-
System
.
nanoTime
()
<=
0L
&&
U
.
compareAndSwapLong
(
this
,
CTL
,
c
,
pc
))
stat
=
w
.
qlock
=
-
1
;
// shrink pool
}
}
}
}
}
}
return
stat
;
}
}
/**
/**
* Scans through queues looking for work while joining a task; if
* Possibly releases (signals) a worker. Called only from scan()
* any present, signals. May return early if more signalling is
* when a worker with apparently inactive status finds a non-empty
* detectably unneeded.
* queue. This requires revalidating all of the associated state
*
* from caller.
* @param task return early if done
*/
* @param origin an index to start scan
private
final
void
helpRelease
(
long
c
,
WorkQueue
[]
ws
,
WorkQueue
w
,
*/
WorkQueue
q
,
int
b
)
{
private
void
helpSignal
(
ForkJoinTask
<?>
task
,
int
origin
)
{
WorkQueue
v
;
int
e
,
i
;
Thread
p
;
WorkQueue
[]
ws
;
WorkQueue
w
;
Thread
p
;
long
c
;
int
m
,
u
,
e
,
i
,
s
;
if
(
w
!=
null
&&
w
.
eventCount
<
0
&&
(
e
=
(
int
)
c
)
>
0
&&
if
(
task
!=
null
&&
task
.
status
>=
0
&&
ws
!=
null
&&
ws
.
length
>
(
i
=
e
&
SMASK
)
&&
(
u
=
(
int
)(
ctl
>>>
32
))
<
0
&&
(
u
>>
UAC_SHIFT
)
<
0
&&
(
v
=
ws
[
i
])
!=
null
&&
ctl
==
c
)
{
(
ws
=
workQueues
)
!=
null
&&
(
m
=
ws
.
length
-
1
)
>=
0
)
{
long
nc
=
(((
long
)(
v
.
nextWait
&
E_MASK
))
|
outer:
for
(
int
k
=
origin
,
j
=
m
;
j
>=
0
;
--
j
)
{
((
long
)((
int
)(
c
>>>
32
)
+
UAC_UNIT
))
<<
32
);
WorkQueue
q
=
ws
[
k
++
&
m
];
int
ne
=
(
e
+
E_SEQ
)
&
E_MASK
;
for
(
int
n
=
m
;;)
{
// limit to at most m signals
if
(
q
!=
null
&&
q
.
base
==
b
&&
w
.
eventCount
<
0
&&
if
(
task
.
status
<
0
)
v
.
eventCount
==
(
e
|
INT_SIGN
)
&&
break
outer
;
U
.
compareAndSwapLong
(
this
,
CTL
,
c
,
nc
))
{
if
(
q
==
null
||
v
.
eventCount
=
ne
;
((
s
=
-
q
.
base
+
q
.
top
)
<=
n
&&
(
n
=
s
)
<=
0
))
if
((
p
=
v
.
parker
)
!=
null
)
break
;
U
.
unpark
(
p
);
if
((
u
=
(
int
)((
c
=
ctl
)
>>>
32
))
>=
0
||
(
e
=
(
int
)
c
)
<=
0
||
m
<
(
i
=
e
&
SMASK
)
||
(
w
=
ws
[
i
])
==
null
)
break
outer
;
long
nc
=
(((
long
)(
w
.
nextWait
&
E_MASK
))
|
((
long
)(
u
+
UAC_UNIT
)
<<
32
));
if
(
w
.
eventCount
!=
(
e
|
INT_SIGN
))
break
outer
;
if
(
U
.
compareAndSwapLong
(
this
,
CTL
,
c
,
nc
))
{
w
.
eventCount
=
(
e
+
E_SEQ
)
&
E_MASK
;
if
((
p
=
w
.
parker
)
!=
null
)
U
.
unpark
(
p
);
if
(--
n
<=
0
)
break
;
}
}
}
}
}
}
}
}
...
@@ -1855,7 +1791,8 @@ public class ForkJoinPool extends AbstractExecutorService {
...
@@ -1855,7 +1791,8 @@ public class ForkJoinPool extends AbstractExecutorService {
*/
*/
private
int
tryHelpStealer
(
WorkQueue
joiner
,
ForkJoinTask
<?>
task
)
{
private
int
tryHelpStealer
(
WorkQueue
joiner
,
ForkJoinTask
<?>
task
)
{
int
stat
=
0
,
steps
=
0
;
// bound to avoid cycles
int
stat
=
0
,
steps
=
0
;
// bound to avoid cycles
if
(
joiner
!=
null
&&
task
!=
null
)
{
// hoist null checks
if
(
task
!=
null
&&
joiner
!=
null
&&
joiner
.
base
-
joiner
.
top
>=
0
)
{
// hoist checks
restart:
for
(;;)
{
restart:
for
(;;)
{
ForkJoinTask
<?>
subtask
=
task
;
// current target
ForkJoinTask
<?>
subtask
=
task
;
// current target
for
(
WorkQueue
j
=
joiner
,
v
;;)
{
// v is stealer of subtask
for
(
WorkQueue
j
=
joiner
,
v
;;)
{
// v is stealer of subtask
...
@@ -1882,7 +1819,7 @@ public class ForkJoinPool extends AbstractExecutorService {
...
@@ -1882,7 +1819,7 @@ public class ForkJoinPool extends AbstractExecutorService {
}
}
}
}
for
(;;)
{
// help stealer or descend to its stealer
for
(;;)
{
// help stealer or descend to its stealer
ForkJoinTask
[]
a
;
int
b
;
ForkJoinTask
[]
a
;
int
b
;
if
(
subtask
.
status
<
0
)
// surround probes with
if
(
subtask
.
status
<
0
)
// surround probes with
continue
restart
;
// consistency checks
continue
restart
;
// consistency checks
if
((
b
=
v
.
base
)
-
v
.
top
<
0
&&
(
a
=
v
.
array
)
!=
null
)
{
if
((
b
=
v
.
base
)
-
v
.
top
<
0
&&
(
a
=
v
.
array
)
!=
null
)
{
...
@@ -1893,13 +1830,23 @@ public class ForkJoinPool extends AbstractExecutorService {
...
@@ -1893,13 +1830,23 @@ public class ForkJoinPool extends AbstractExecutorService {
v
.
currentSteal
!=
subtask
)
v
.
currentSteal
!=
subtask
)
continue
restart
;
// stale
continue
restart
;
// stale
stat
=
1
;
// apparent progress
stat
=
1
;
// apparent progress
if
(
t
!=
null
&&
v
.
base
==
b
&&
if
(
v
.
base
==
b
)
{
U
.
compareAndSwapObject
(
a
,
i
,
t
,
null
))
{
if
(
t
==
null
)
v
.
base
=
b
+
1
;
// help stealer
break
restart
;
joiner
.
runSubtask
(
t
);
if
(
U
.
compareAndSwapObject
(
a
,
i
,
t
,
null
))
{
U
.
putOrderedInt
(
v
,
QBASE
,
b
+
1
);
ForkJoinTask
<?>
ps
=
joiner
.
currentSteal
;
int
jt
=
joiner
.
top
;
do
{
joiner
.
currentSteal
=
t
;
t
.
doExec
();
// clear local tasks too
}
while
(
task
.
status
>=
0
&&
joiner
.
top
!=
jt
&&
(
t
=
joiner
.
pop
())
!=
null
);
joiner
.
currentSteal
=
ps
;
break
restart
;
}
}
}
else
if
(
v
.
base
==
b
&&
++
steps
==
MAX_HELP
)
break
restart
;
// v apparently stalled
}
}
else
{
// empty -- try to descend
else
{
// empty -- try to descend
ForkJoinTask
<?>
next
=
v
.
currentJoin
;
ForkJoinTask
<?>
next
=
v
.
currentJoin
;
...
@@ -1926,27 +1873,45 @@ public class ForkJoinPool extends AbstractExecutorService {
...
@@ -1926,27 +1873,45 @@ public class ForkJoinPool extends AbstractExecutorService {
* and run tasks within the target's computation.
* and run tasks within the target's computation.
*
*
* @param task the task to join
* @param task the task to join
* @param mode if shared, exit upon completing any task
* @param maxTasks the maximum number of other tasks to run
* if all workers are active
*/
*/
final
int
helpComplete
(
WorkQueue
joiner
,
CountedCompleter
<?>
task
,
private
int
helpComplete
(
ForkJoinTask
<?>
task
,
int
mode
)
{
int
maxTasks
)
{
WorkQueue
[]
ws
;
WorkQueue
q
;
int
m
,
n
,
s
,
u
;
WorkQueue
[]
ws
;
int
m
;
if
(
task
!=
null
&&
(
ws
=
workQueues
)
!=
null
&&
int
s
=
0
;
(
m
=
ws
.
length
-
1
)
>=
0
)
{
if
((
ws
=
workQueues
)
!=
null
&&
(
m
=
ws
.
length
-
1
)
>=
0
&&
for
(
int
j
=
1
,
origin
=
j
;;)
{
joiner
!=
null
&&
task
!=
null
)
{
int
j
=
joiner
.
poolIndex
;
int
scans
=
m
+
m
+
1
;
long
c
=
0L
;
// for stability check
for
(
int
k
=
scans
;
;
j
+=
2
)
{
WorkQueue
q
;
if
((
s
=
task
.
status
)
<
0
)
if
((
s
=
task
.
status
)
<
0
)
return
s
;
break
;
if
((
q
=
ws
[
j
&
m
])
!=
null
&&
q
.
pollAndExecCC
(
task
))
{
else
if
(
joiner
.
internalPopAndExecCC
(
task
))
{
origin
=
j
;
if
(--
maxTasks
<=
0
)
{
if
(
mode
==
SHARED_QUEUE
&&
s
=
task
.
status
;
((
u
=
(
int
)(
ctl
>>>
32
))
>=
0
||
(
u
>>
UAC_SHIFT
)
>=
0
))
break
;
break
;
}
k
=
scans
;
}
}
else
if
((
j
=
(
j
+
2
)
&
m
)
==
origin
)
else
if
((
s
=
task
.
status
)
<
0
)
break
;
break
;
else
if
((
q
=
ws
[
j
&
m
])
!=
null
&&
q
.
pollAndExecCC
(
task
))
{
if
(--
maxTasks
<=
0
)
{
s
=
task
.
status
;
break
;
}
k
=
scans
;
}
else
if
(--
k
<
0
)
{
if
(
c
==
(
c
=
ctl
))
break
;
k
=
scans
;
}
}
}
}
}
return
0
;
return
s
;
}
}
/**
/**
...
@@ -1955,17 +1920,22 @@ public class ForkJoinPool extends AbstractExecutorService {
...
@@ -1955,17 +1920,22 @@ public class ForkJoinPool extends AbstractExecutorService {
* for blocking. Fails on contention or termination. Otherwise,
* for blocking. Fails on contention or termination. Otherwise,
* adds a new thread if no idle workers are available and pool
* adds a new thread if no idle workers are available and pool
* may become starved.
* may become starved.
*
* @param c the assumed ctl value
*/
*/
final
boolean
tryCompensate
()
{
final
boolean
tryCompensate
(
long
c
)
{
int
pc
=
config
&
SMASK
,
e
,
i
,
tc
;
long
c
;
WorkQueue
[]
ws
=
workQueues
;
WorkQueue
[]
ws
;
WorkQueue
w
;
Thread
p
;
int
pc
=
parallelism
,
e
=
(
int
)
c
,
m
,
tc
;
if
((
ws
=
workQueues
)
!=
null
&&
(
e
=
(
int
)(
c
=
ctl
))
>=
0
)
{
if
(
ws
!=
null
&&
(
m
=
ws
.
length
-
1
)
>=
0
&&
e
>=
0
&&
ctl
==
c
)
{
if
(
e
!=
0
&&
(
i
=
e
&
SMASK
)
<
ws
.
length
&&
WorkQueue
w
=
ws
[
e
&
m
];
(
w
=
ws
[
i
])
!=
null
&&
w
.
eventCount
==
(
e
|
INT_SIGN
))
{
if
(
e
!=
0
&&
w
!=
null
)
{
Thread
p
;
long
nc
=
((
long
)(
w
.
nextWait
&
E_MASK
)
|
long
nc
=
((
long
)(
w
.
nextWait
&
E_MASK
)
|
(
c
&
(
AC_MASK
|
TC_MASK
)));
(
c
&
(
AC_MASK
|
TC_MASK
)));
if
(
U
.
compareAndSwapLong
(
this
,
CTL
,
c
,
nc
))
{
int
ne
=
(
e
+
E_SEQ
)
&
E_MASK
;
w
.
eventCount
=
(
e
+
E_SEQ
)
&
E_MASK
;
if
(
w
.
eventCount
==
(
e
|
INT_SIGN
)
&&
U
.
compareAndSwapLong
(
this
,
CTL
,
c
,
nc
))
{
w
.
eventCount
=
ne
;
if
((
p
=
w
.
parker
)
!=
null
)
if
((
p
=
w
.
parker
)
!=
null
)
U
.
unpark
(
p
);
U
.
unpark
(
p
);
return
true
;
// replace with idle worker
return
true
;
// replace with idle worker
...
@@ -2008,23 +1978,20 @@ public class ForkJoinPool extends AbstractExecutorService {
...
@@ -2008,23 +1978,20 @@ public class ForkJoinPool extends AbstractExecutorService {
*/
*/
final
int
awaitJoin
(
WorkQueue
joiner
,
ForkJoinTask
<?>
task
)
{
final
int
awaitJoin
(
WorkQueue
joiner
,
ForkJoinTask
<?>
task
)
{
int
s
=
0
;
int
s
=
0
;
if
(
joiner
!=
null
&&
task
!=
null
&&
(
s
=
task
.
status
)
>=
0
)
{
if
(
task
!=
null
&&
(
s
=
task
.
status
)
>=
0
&&
joiner
!=
null
)
{
ForkJoinTask
<?>
prevJoin
=
joiner
.
currentJoin
;
ForkJoinTask
<?>
prevJoin
=
joiner
.
currentJoin
;
joiner
.
currentJoin
=
task
;
joiner
.
currentJoin
=
task
;
do
{}
while
((
s
=
task
.
status
)
>=
0
&&
!
joiner
.
isEmpty
()
&&
do
{}
while
(
joiner
.
tryRemoveAndExec
(
task
)
&&
// process local tasks
joiner
.
tryRemoveAndExec
(
task
));
// process local tasks
(
s
=
task
.
status
)
>=
0
);
if
(
s
>=
0
&&
(
s
=
task
.
status
)
>=
0
)
{
if
(
s
>=
0
&&
(
task
instanceof
CountedCompleter
))
helpSignal
(
task
,
joiner
.
poolIndex
);
s
=
helpComplete
(
joiner
,
(
CountedCompleter
<?>)
task
,
Integer
.
MAX_VALUE
);
if
((
s
=
task
.
status
)
>=
0
&&
long
cc
=
0
;
// for stability checks
(
task
instanceof
CountedCompleter
))
s
=
helpComplete
(
task
,
LIFO_QUEUE
);
}
while
(
s
>=
0
&&
(
s
=
task
.
status
)
>=
0
)
{
while
(
s
>=
0
&&
(
s
=
task
.
status
)
>=
0
)
{
if
((!
joiner
.
isEmpty
()
||
// try helping
if
((
s
=
tryHelpStealer
(
joiner
,
task
))
==
0
&&
(
s
=
tryHelpStealer
(
joiner
,
task
))
==
0
)
&&
(
s
=
task
.
status
)
>=
0
)
{
(
s
=
task
.
status
)
>=
0
)
{
helpSignal
(
task
,
joiner
.
poolIndex
);
if
(!
tryCompensate
(
cc
))
if
((
s
=
task
.
status
)
>=
0
&&
tryCompensate
())
{
cc
=
ctl
;
else
{
if
(
task
.
trySetSignal
()
&&
(
s
=
task
.
status
)
>=
0
)
{
if
(
task
.
trySetSignal
()
&&
(
s
=
task
.
status
)
>=
0
)
{
synchronized
(
task
)
{
synchronized
(
task
)
{
if
(
task
.
status
>=
0
)
{
if
(
task
.
status
>=
0
)
{
...
@@ -2037,9 +2004,11 @@ public class ForkJoinPool extends AbstractExecutorService {
...
@@ -2037,9 +2004,11 @@ public class ForkJoinPool extends AbstractExecutorService {
task
.
notifyAll
();
task
.
notifyAll
();
}
}
}
}
long
c
;
// re-
activate
long
c
;
// re
activate
do
{}
while
(!
U
.
compareAndSwapLong
do
{}
while
(!
U
.
compareAndSwapLong
(
this
,
CTL
,
c
=
ctl
,
c
+
AC_UNIT
));
(
this
,
CTL
,
c
=
ctl
,
((
c
&
~
AC_MASK
)
|
((
c
&
AC_MASK
)
+
AC_UNIT
))));
}
}
}
}
}
}
...
@@ -2061,15 +2030,11 @@ public class ForkJoinPool extends AbstractExecutorService {
...
@@ -2061,15 +2030,11 @@ public class ForkJoinPool extends AbstractExecutorService {
if
(
joiner
!=
null
&&
task
!=
null
&&
(
s
=
task
.
status
)
>=
0
)
{
if
(
joiner
!=
null
&&
task
!=
null
&&
(
s
=
task
.
status
)
>=
0
)
{
ForkJoinTask
<?>
prevJoin
=
joiner
.
currentJoin
;
ForkJoinTask
<?>
prevJoin
=
joiner
.
currentJoin
;
joiner
.
currentJoin
=
task
;
joiner
.
currentJoin
=
task
;
do
{}
while
((
s
=
task
.
status
)
>=
0
&&
!
joiner
.
isEmpty
()
&&
do
{}
while
(
joiner
.
tryRemoveAndExec
(
task
)
&&
// process local tasks
joiner
.
tryRemoveAndExec
(
task
));
(
s
=
task
.
status
)
>=
0
);
if
(
s
>=
0
&&
(
s
=
task
.
status
)
>=
0
)
{
if
(
s
>=
0
)
{
helpSignal
(
task
,
joiner
.
poolIndex
);
if
(
task
instanceof
CountedCompleter
)
if
((
s
=
task
.
status
)
>=
0
&&
helpComplete
(
joiner
,
(
CountedCompleter
<?>)
task
,
Integer
.
MAX_VALUE
);
(
task
instanceof
CountedCompleter
))
s
=
helpComplete
(
task
,
LIFO_QUEUE
);
}
if
(
s
>=
0
&&
joiner
.
isEmpty
())
{
do
{}
while
(
task
.
status
>=
0
&&
do
{}
while
(
task
.
status
>=
0
&&
tryHelpStealer
(
joiner
,
task
)
>
0
);
tryHelpStealer
(
joiner
,
task
)
>
0
);
}
}
...
@@ -2081,14 +2046,14 @@ public class ForkJoinPool extends AbstractExecutorService {
...
@@ -2081,14 +2046,14 @@ public class ForkJoinPool extends AbstractExecutorService {
* Returns a (probably) non-empty steal queue, if one is found
* Returns a (probably) non-empty steal queue, if one is found
* during a scan, else null. This method must be retried by
* during a scan, else null. This method must be retried by
* caller if, by the time it tries to use the queue, it is empty.
* caller if, by the time it tries to use the queue, it is empty.
* @param r a (random) seed for scanning
*/
*/
private
WorkQueue
findNonEmptyStealQueue
(
int
r
)
{
private
WorkQueue
findNonEmptyStealQueue
()
{
int
r
=
ThreadLocalRandom
.
nextSecondarySeed
();
for
(;;)
{
for
(;;)
{
int
ps
=
plock
,
m
;
WorkQueue
[]
ws
;
WorkQueue
q
;
int
ps
=
plock
,
m
;
WorkQueue
[]
ws
;
WorkQueue
q
;
if
((
ws
=
workQueues
)
!=
null
&&
(
m
=
ws
.
length
-
1
)
>=
0
)
{
if
((
ws
=
workQueues
)
!=
null
&&
(
m
=
ws
.
length
-
1
)
>=
0
)
{
for
(
int
j
=
(
m
+
1
)
<<
2
;
j
>=
0
;
--
j
)
{
for
(
int
j
=
(
m
+
1
)
<<
2
;
j
>=
0
;
--
j
)
{
if
((
q
=
ws
[(((
r
+
j
)
<<
1
)
|
1
)
&
m
])
!=
null
&&
if
((
q
=
ws
[(((
r
-
j
)
<<
1
)
|
1
)
&
m
])
!=
null
&&
q
.
base
-
q
.
top
<
0
)
q
.
base
-
q
.
top
<
0
)
return
q
;
return
q
;
}
}
...
@@ -2105,35 +2070,36 @@ public class ForkJoinPool extends AbstractExecutorService {
...
@@ -2105,35 +2070,36 @@ public class ForkJoinPool extends AbstractExecutorService {
* find tasks either.
* find tasks either.
*/
*/
final
void
helpQuiescePool
(
WorkQueue
w
)
{
final
void
helpQuiescePool
(
WorkQueue
w
)
{
ForkJoinTask
<?>
ps
=
w
.
currentSteal
;
for
(
boolean
active
=
true
;;)
{
for
(
boolean
active
=
true
;;)
{
long
c
;
WorkQueue
q
;
ForkJoinTask
<?>
t
;
int
b
;
long
c
;
WorkQueue
q
;
ForkJoinTask
<?>
t
;
int
b
;
while
((
t
=
w
.
nextLocalTask
())
!=
null
)
{
while
((
t
=
w
.
nextLocalTask
())
!=
null
)
if
(
w
.
base
-
w
.
top
<
0
)
signalWork
(
w
);
t
.
doExec
();
t
.
doExec
();
}
if
((
q
=
findNonEmptyStealQueue
())
!=
null
)
{
if
((
q
=
findNonEmptyStealQueue
(
w
.
nextSeed
()))
!=
null
)
{
if
(!
active
)
{
// re-establish active count
if
(!
active
)
{
// re-establish active count
active
=
true
;
active
=
true
;
do
{}
while
(!
U
.
compareAndSwapLong
do
{}
while
(!
U
.
compareAndSwapLong
(
this
,
CTL
,
c
=
ctl
,
c
+
AC_UNIT
));
(
this
,
CTL
,
c
=
ctl
,
((
c
&
~
AC_MASK
)
|
((
c
&
AC_MASK
)
+
AC_UNIT
))));
}
}
if
((
b
=
q
.
base
)
-
q
.
top
<
0
&&
(
t
=
q
.
pollAt
(
b
))
!=
null
)
{
if
((
b
=
q
.
base
)
-
q
.
top
<
0
&&
(
t
=
q
.
pollAt
(
b
))
!=
null
)
{
if
(
q
.
base
-
q
.
top
<
0
)
(
w
.
currentSteal
=
t
).
doExec
();
signalWork
(
q
);
w
.
currentSteal
=
ps
;
w
.
runSubtask
(
t
);
}
}
}
}
else
if
(
active
)
{
// decrement active count without queuing
else
if
(
active
)
{
// decrement active count without queuing
long
nc
=
(
c
=
ctl
)
-
AC_UNIT
;
long
nc
=
(
(
c
=
ctl
)
&
~
AC_MASK
)
|
((
c
&
AC_MASK
)
-
AC_UNIT
)
;
if
((
int
)(
nc
>>
AC_SHIFT
)
+
(
config
&
SMASK
)
==
0
)
if
((
int
)(
nc
>>
AC_SHIFT
)
+
parallelism
==
0
)
return
;
// bypass decrement-then-increment
break
;
// bypass decrement-then-increment
if
(
U
.
compareAndSwapLong
(
this
,
CTL
,
c
,
nc
))
if
(
U
.
compareAndSwapLong
(
this
,
CTL
,
c
,
nc
))
active
=
false
;
active
=
false
;
}
}
else
if
((
int
)((
c
=
ctl
)
>>
AC_SHIFT
)
+
(
config
&
SMASK
)
==
0
&&
else
if
((
int
)((
c
=
ctl
)
>>
AC_SHIFT
)
+
parallelism
<=
0
&&
U
.
compareAndSwapLong
(
this
,
CTL
,
c
,
c
+
AC_UNIT
))
U
.
compareAndSwapLong
return
;
(
this
,
CTL
,
c
,
((
c
&
~
AC_MASK
)
|
((
c
&
AC_MASK
)
+
AC_UNIT
))))
break
;
}
}
}
}
...
@@ -2147,13 +2113,10 @@ public class ForkJoinPool extends AbstractExecutorService {
...
@@ -2147,13 +2113,10 @@ public class ForkJoinPool extends AbstractExecutorService {
WorkQueue
q
;
int
b
;
WorkQueue
q
;
int
b
;
if
((
t
=
w
.
nextLocalTask
())
!=
null
)
if
((
t
=
w
.
nextLocalTask
())
!=
null
)
return
t
;
return
t
;
if
((
q
=
findNonEmptyStealQueue
(
w
.
nextSeed
()
))
==
null
)
if
((
q
=
findNonEmptyStealQueue
())
==
null
)
return
null
;
return
null
;
if
((
b
=
q
.
base
)
-
q
.
top
<
0
&&
(
t
=
q
.
pollAt
(
b
))
!=
null
)
{
if
((
b
=
q
.
base
)
-
q
.
top
<
0
&&
(
t
=
q
.
pollAt
(
b
))
!=
null
)
if
(
q
.
base
-
q
.
top
<
0
)
signalWork
(
q
);
return
t
;
return
t
;
}
}
}
}
}
...
@@ -2206,7 +2169,7 @@ public class ForkJoinPool extends AbstractExecutorService {
...
@@ -2206,7 +2169,7 @@ public class ForkJoinPool extends AbstractExecutorService {
static
int
getSurplusQueuedTaskCount
()
{
static
int
getSurplusQueuedTaskCount
()
{
Thread
t
;
ForkJoinWorkerThread
wt
;
ForkJoinPool
pool
;
WorkQueue
q
;
Thread
t
;
ForkJoinWorkerThread
wt
;
ForkJoinPool
pool
;
WorkQueue
q
;
if
(((
t
=
Thread
.
currentThread
())
instanceof
ForkJoinWorkerThread
))
{
if
(((
t
=
Thread
.
currentThread
())
instanceof
ForkJoinWorkerThread
))
{
int
p
=
(
pool
=
(
wt
=
(
ForkJoinWorkerThread
)
t
).
pool
).
config
&
SMASK
;
int
p
=
(
pool
=
(
wt
=
(
ForkJoinWorkerThread
)
t
).
pool
).
parallelism
;
int
n
=
(
q
=
wt
.
workQueue
).
top
-
q
.
base
;
int
n
=
(
q
=
wt
.
workQueue
).
top
-
q
.
base
;
int
a
=
(
int
)(
pool
.
ctl
>>
AC_SHIFT
)
+
p
;
int
a
=
(
int
)(
pool
.
ctl
>>
AC_SHIFT
)
+
p
;
return
n
-
(
a
>
(
p
>>>=
1
)
?
0
:
return
n
-
(
a
>
(
p
>>>=
1
)
?
0
:
...
@@ -2236,7 +2199,7 @@ public class ForkJoinPool extends AbstractExecutorService {
...
@@ -2236,7 +2199,7 @@ public class ForkJoinPool extends AbstractExecutorService {
*/
*/
private
boolean
tryTerminate
(
boolean
now
,
boolean
enable
)
{
private
boolean
tryTerminate
(
boolean
now
,
boolean
enable
)
{
int
ps
;
int
ps
;
if
(
this
==
common
)
// cannot shut down
if
(
this
==
common
)
// cannot shut down
return
false
;
return
false
;
if
((
ps
=
plock
)
>=
0
)
{
// enable by setting plock
if
((
ps
=
plock
)
>=
0
)
{
// enable by setting plock
if
(!
enable
)
if
(!
enable
)
...
@@ -2250,7 +2213,7 @@ public class ForkJoinPool extends AbstractExecutorService {
...
@@ -2250,7 +2213,7 @@ public class ForkJoinPool extends AbstractExecutorService {
}
}
for
(
long
c
;;)
{
for
(
long
c
;;)
{
if
(((
c
=
ctl
)
&
STOP_BIT
)
!=
0
)
{
// already terminating
if
(((
c
=
ctl
)
&
STOP_BIT
)
!=
0
)
{
// already terminating
if
((
short
)(
c
>>>
TC_SHIFT
)
==
-(
config
&
SMASK
)
)
{
if
((
short
)(
c
>>>
TC_SHIFT
)
+
parallelism
<=
0
)
{
synchronized
(
this
)
{
synchronized
(
this
)
{
notifyAll
();
// signal when 0 workers
notifyAll
();
// signal when 0 workers
}
}
...
@@ -2259,17 +2222,15 @@ public class ForkJoinPool extends AbstractExecutorService {
...
@@ -2259,17 +2222,15 @@ public class ForkJoinPool extends AbstractExecutorService {
}
}
if
(!
now
)
{
// check if idle & no tasks
if
(!
now
)
{
// check if idle & no tasks
WorkQueue
[]
ws
;
WorkQueue
w
;
WorkQueue
[]
ws
;
WorkQueue
w
;
if
((
int
)(
c
>>
AC_SHIFT
)
!=
-(
config
&
SMASK
)
)
if
((
int
)(
c
>>
AC_SHIFT
)
+
parallelism
>
0
)
return
false
;
return
false
;
if
((
ws
=
workQueues
)
!=
null
)
{
if
((
ws
=
workQueues
)
!=
null
)
{
for
(
int
i
=
0
;
i
<
ws
.
length
;
++
i
)
{
for
(
int
i
=
0
;
i
<
ws
.
length
;
++
i
)
{
if
((
w
=
ws
[
i
])
!=
null
)
{
if
((
w
=
ws
[
i
])
!=
null
&&
if
(!
w
.
isEmpty
())
{
// signal unprocessed tasks
(!
w
.
isEmpty
()
||
signalWork
(
w
);
((
i
&
1
)
!=
0
&&
w
.
eventCount
>=
0
)))
{
return
false
;
signalWork
(
ws
,
w
);
}
return
false
;
if
((
i
&
1
)
!=
0
&&
w
.
eventCount
>=
0
)
return
false
;
// unqueued inactive worker
}
}
}
}
}
}
...
@@ -2336,116 +2297,67 @@ public class ForkJoinPool extends AbstractExecutorService {
...
@@ -2336,116 +2297,67 @@ public class ForkJoinPool extends AbstractExecutorService {
/**
/**
* Tries to pop the given task from submitter's queue in common pool.
* Tries to pop the given task from submitter's queue in common pool.
*/
*/
static
boolean
tryExternalUnpush
(
ForkJoinTask
<?>
t
)
{
final
boolean
tryExternalUnpush
(
ForkJoinTask
<?>
task
)
{
ForkJoinPool
p
;
WorkQueue
[]
ws
;
WorkQueue
q
;
WorkQueue
joiner
;
ForkJoinTask
<?>[]
a
;
int
m
,
s
;
ForkJoinTask
<?>[]
a
;
int
m
,
s
,
z
;
WorkQueue
[]
ws
=
workQueues
;
if
(
t
!=
null
&&
int
z
=
ThreadLocalRandom
.
getProbe
();
(
z
=
ThreadLocalRandom
.
getProbe
())
!=
0
&&
boolean
popped
=
false
;
(
p
=
common
)
!=
null
&&
if
(
ws
!=
null
&&
(
m
=
ws
.
length
-
1
)
>=
0
&&
(
ws
=
p
.
workQueues
)
!=
null
&&
(
joiner
=
ws
[
z
&
m
&
SQMASK
])
!=
null
&&
(
m
=
ws
.
length
-
1
)
>=
0
&&
joiner
.
base
!=
(
s
=
joiner
.
top
)
&&
(
q
=
ws
[
m
&
z
&
SQMASK
])
!=
null
&&
(
a
=
joiner
.
array
)
!=
null
)
{
(
s
=
q
.
top
)
!=
q
.
base
&&
(
a
=
q
.
array
)
!=
null
)
{
long
j
=
(((
a
.
length
-
1
)
&
(
s
-
1
))
<<
ASHIFT
)
+
ABASE
;
long
j
=
(((
a
.
length
-
1
)
&
(
s
-
1
))
<<
ASHIFT
)
+
ABASE
;
if
(
U
.
getObject
(
a
,
j
)
==
t
&&
if
(
U
.
getObject
(
a
,
j
)
==
task
&&
U
.
compareAndSwapInt
(
q
,
QLOCK
,
0
,
1
))
{
U
.
compareAndSwapInt
(
joiner
,
QLOCK
,
0
,
1
))
{
if
(
q
.
array
==
a
&&
q
.
top
==
s
&&
// recheck
if
(
joiner
.
top
==
s
&&
joiner
.
array
==
a
&&
U
.
compareAndSwapObject
(
a
,
j
,
t
,
null
))
{
U
.
compareAndSwapObject
(
a
,
j
,
task
,
null
))
{
q
.
top
=
s
-
1
;
joiner
.
top
=
s
-
1
;
q
.
qlock
=
0
;
popped
=
true
;
return
true
;
}
}
q
.
qlock
=
0
;
joiner
.
qlock
=
0
;
}
}
}
}
return
false
;
return
popped
;
}
}
/**
final
int
externalHelpComplete
(
CountedCompleter
<?>
task
,
int
maxTasks
)
{
* Tries to pop and run local tasks within the same computation
WorkQueue
joiner
;
int
m
;
* as the given root. On failure, tries to help complete from
WorkQueue
[]
ws
=
workQueues
;
* other queues via helpComplete.
int
j
=
ThreadLocalRandom
.
getProbe
();
*/
int
s
=
0
;
private
void
externalHelpComplete
(
WorkQueue
q
,
ForkJoinTask
<?>
root
)
{
if
(
ws
!=
null
&&
(
m
=
ws
.
length
-
1
)
>=
0
&&
ForkJoinTask
<?>[]
a
;
int
m
;
(
joiner
=
ws
[
j
&
m
&
SQMASK
])
!=
null
&&
task
!=
null
)
{
if
(
q
!=
null
&&
(
a
=
q
.
array
)
!=
null
&&
(
m
=
(
a
.
length
-
1
))
>=
0
&&
int
scans
=
m
+
m
+
1
;
root
!=
null
&&
root
.
status
>=
0
)
{
long
c
=
0L
;
// for stability check
for
(;;)
{
j
|=
1
;
// poll odd queues
int
s
,
u
;
Object
o
;
CountedCompleter
<?>
task
=
null
;
for
(
int
k
=
scans
;
;
j
+=
2
)
{
if
((
s
=
q
.
top
)
-
q
.
base
>
0
)
{
WorkQueue
q
;
long
j
=
((
m
&
(
s
-
1
))
<<
ASHIFT
)
+
ABASE
;
if
((
s
=
task
.
status
)
<
0
)
if
((
o
=
U
.
getObject
(
a
,
j
))
!=
null
&&
break
;
(
o
instanceof
CountedCompleter
))
{
else
if
(
joiner
.
externalPopAndExecCC
(
task
))
{
CountedCompleter
<?>
t
=
(
CountedCompleter
<?>)
o
,
r
=
t
;
if
(--
maxTasks
<=
0
)
{
do
{
s
=
task
.
status
;
if
(
r
==
root
)
{
break
;
if
(
U
.
compareAndSwapInt
(
q
,
QLOCK
,
0
,
1
))
{
if
(
q
.
array
==
a
&&
q
.
top
==
s
&&
U
.
compareAndSwapObject
(
a
,
j
,
t
,
null
))
{
q
.
top
=
s
-
1
;
task
=
t
;
}
q
.
qlock
=
0
;
}
break
;
}
}
while
((
r
=
r
.
completer
)
!=
null
);
}
}
k
=
scans
;
}
}
if
(
task
!=
null
)
else
if
((
s
=
task
.
status
)
<
0
)
task
.
doExec
();
if
(
root
.
status
<
0
||
(
config
!=
0
&&
((
u
=
(
int
)(
ctl
>>>
32
))
>=
0
||
(
u
>>
UAC_SHIFT
)
>=
0
)))
break
;
if
(
task
==
null
)
{
helpSignal
(
root
,
q
.
poolIndex
);
if
(
root
.
status
>=
0
)
helpComplete
(
root
,
SHARED_QUEUE
);
break
;
break
;
}
else
if
((
q
=
ws
[
j
&
m
])
!=
null
&&
q
.
pollAndExecCC
(
task
))
{
}
if
(--
maxTasks
<=
0
)
{
}
s
=
task
.
status
;
}
break
;
/**
* Tries to help execute or signal availability of the given task
* from submitter's queue in common pool.
*/
static
void
externalHelpJoin
(
ForkJoinTask
<?>
t
)
{
// Some hard-to-avoid overlap with tryExternalUnpush
ForkJoinPool
p
;
WorkQueue
[]
ws
;
WorkQueue
q
,
w
;
ForkJoinTask
<?>[]
a
;
int
m
,
s
,
n
,
z
;
if
(
t
!=
null
&&
(
z
=
ThreadLocalRandom
.
getProbe
())
!=
0
&&
(
p
=
common
)
!=
null
&&
(
ws
=
p
.
workQueues
)
!=
null
&&
(
m
=
ws
.
length
-
1
)
>=
0
&&
(
q
=
ws
[
m
&
z
&
SQMASK
])
!=
null
&&
(
a
=
q
.
array
)
!=
null
)
{
int
am
=
a
.
length
-
1
;
if
((
s
=
q
.
top
)
!=
q
.
base
)
{
long
j
=
((
am
&
(
s
-
1
))
<<
ASHIFT
)
+
ABASE
;
if
(
U
.
getObject
(
a
,
j
)
==
t
&&
U
.
compareAndSwapInt
(
q
,
QLOCK
,
0
,
1
))
{
if
(
q
.
array
==
a
&&
q
.
top
==
s
&&
U
.
compareAndSwapObject
(
a
,
j
,
t
,
null
))
{
q
.
top
=
s
-
1
;
q
.
qlock
=
0
;
t
.
doExec
();
}
}
else
k
=
scans
;
q
.
qlock
=
0
;
}
else
if
(--
k
<
0
)
{
if
(
c
==
(
c
=
ctl
))
break
;
k
=
scans
;
}
}
}
if
(
t
.
status
>=
0
)
{
if
(
t
instanceof
CountedCompleter
)
p
.
externalHelpComplete
(
q
,
t
);
else
p
.
helpSignal
(
t
,
q
.
poolIndex
);
}
}
}
}
return
s
;
}
}
// Exported methods
// Exported methods
...
@@ -2517,7 +2429,7 @@ public class ForkJoinPool extends AbstractExecutorService {
...
@@ -2517,7 +2429,7 @@ public class ForkJoinPool extends AbstractExecutorService {
this
(
checkParallelism
(
parallelism
),
this
(
checkParallelism
(
parallelism
),
checkFactory
(
factory
),
checkFactory
(
factory
),
handler
,
handler
,
asyncMode
,
(
asyncMode
?
FIFO_QUEUE
:
LIFO_QUEUE
)
,
"ForkJoinPool-"
+
nextPoolId
()
+
"-worker-"
);
"ForkJoinPool-"
+
nextPoolId
()
+
"-worker-"
);
checkPermission
();
checkPermission
();
}
}
...
@@ -2543,12 +2455,13 @@ public class ForkJoinPool extends AbstractExecutorService {
...
@@ -2543,12 +2455,13 @@ public class ForkJoinPool extends AbstractExecutorService {
private
ForkJoinPool
(
int
parallelism
,
private
ForkJoinPool
(
int
parallelism
,
ForkJoinWorkerThreadFactory
factory
,
ForkJoinWorkerThreadFactory
factory
,
UncaughtExceptionHandler
handler
,
UncaughtExceptionHandler
handler
,
boolean
asyncM
ode
,
int
m
ode
,
String
workerNamePrefix
)
{
String
workerNamePrefix
)
{
this
.
workerNamePrefix
=
workerNamePrefix
;
this
.
workerNamePrefix
=
workerNamePrefix
;
this
.
factory
=
factory
;
this
.
factory
=
factory
;
this
.
ueh
=
handler
;
this
.
ueh
=
handler
;
this
.
config
=
parallelism
|
(
asyncMode
?
(
FIFO_QUEUE
<<
16
)
:
0
);
this
.
mode
=
(
short
)
mode
;
this
.
parallelism
=
(
short
)
parallelism
;
long
np
=
(
long
)(-
parallelism
);
// offset ctl counts
long
np
=
(
long
)(-
parallelism
);
// offset ctl counts
this
.
ctl
=
((
np
<<
AC_SHIFT
)
&
AC_MASK
)
|
((
np
<<
TC_SHIFT
)
&
TC_MASK
);
this
.
ctl
=
((
np
<<
AC_SHIFT
)
&
AC_MASK
)
|
((
np
<<
TC_SHIFT
)
&
TC_MASK
);
}
}
...
@@ -2736,8 +2649,8 @@ public class ForkJoinPool extends AbstractExecutorService {
...
@@ -2736,8 +2649,8 @@ public class ForkJoinPool extends AbstractExecutorService {
* @return the targeted parallelism level of this pool
* @return the targeted parallelism level of this pool
*/
*/
public
int
getParallelism
()
{
public
int
getParallelism
()
{
int
par
=
(
config
&
SMASK
)
;
int
par
;
return
(
par
>
0
)
?
par
:
1
;
return
(
(
par
=
parallelism
)
>
0
)
?
par
:
1
;
}
}
/**
/**
...
@@ -2759,7 +2672,7 @@ public class ForkJoinPool extends AbstractExecutorService {
...
@@ -2759,7 +2672,7 @@ public class ForkJoinPool extends AbstractExecutorService {
* @return the number of worker threads
* @return the number of worker threads
*/
*/
public
int
getPoolSize
()
{
public
int
getPoolSize
()
{
return
(
config
&
SMASK
)
+
(
short
)(
ctl
>>>
TC_SHIFT
);
return
parallelism
+
(
short
)(
ctl
>>>
TC_SHIFT
);
}
}
/**
/**
...
@@ -2769,7 +2682,7 @@ public class ForkJoinPool extends AbstractExecutorService {
...
@@ -2769,7 +2682,7 @@ public class ForkJoinPool extends AbstractExecutorService {
* @return {@code true} if this pool uses async mode
* @return {@code true} if this pool uses async mode
*/
*/
public
boolean
getAsyncMode
()
{
public
boolean
getAsyncMode
()
{
return
(
config
>>>
16
)
==
FIFO_QUEUE
;
return
mode
==
FIFO_QUEUE
;
}
}
/**
/**
...
@@ -2800,7 +2713,7 @@ public class ForkJoinPool extends AbstractExecutorService {
...
@@ -2800,7 +2713,7 @@ public class ForkJoinPool extends AbstractExecutorService {
* @return the number of active threads
* @return the number of active threads
*/
*/
public
int
getActiveThreadCount
()
{
public
int
getActiveThreadCount
()
{
int
r
=
(
config
&
SMASK
)
+
(
int
)(
ctl
>>
AC_SHIFT
);
int
r
=
parallelism
+
(
int
)(
ctl
>>
AC_SHIFT
);
return
(
r
<=
0
)
?
0
:
r
;
// suppress momentarily negative values
return
(
r
<=
0
)
?
0
:
r
;
// suppress momentarily negative values
}
}
...
@@ -2816,7 +2729,7 @@ public class ForkJoinPool extends AbstractExecutorService {
...
@@ -2816,7 +2729,7 @@ public class ForkJoinPool extends AbstractExecutorService {
* @return {@code true} if all threads are currently idle
* @return {@code true} if all threads are currently idle
*/
*/
public
boolean
isQuiescent
()
{
public
boolean
isQuiescent
()
{
return
(
int
)(
ctl
>>
AC_SHIFT
)
+
(
config
&
SMASK
)
=
=
0
;
return
parallelism
+
(
int
)(
ctl
>>
AC_SHIFT
)
<
=
0
;
}
}
/**
/**
...
@@ -2979,7 +2892,7 @@ public class ForkJoinPool extends AbstractExecutorService {
...
@@ -2979,7 +2892,7 @@ public class ForkJoinPool extends AbstractExecutorService {
}
}
}
}
}
}
int
pc
=
(
config
&
SMASK
)
;
int
pc
=
parallelism
;
int
tc
=
pc
+
(
short
)(
c
>>>
TC_SHIFT
);
int
tc
=
pc
+
(
short
)(
c
>>>
TC_SHIFT
);
int
ac
=
pc
+
(
int
)(
c
>>
AC_SHIFT
);
int
ac
=
pc
+
(
int
)(
c
>>
AC_SHIFT
);
if
(
ac
<
0
)
// ignore transient negative
if
(
ac
<
0
)
// ignore transient negative
...
@@ -3052,7 +2965,7 @@ public class ForkJoinPool extends AbstractExecutorService {
...
@@ -3052,7 +2965,7 @@ public class ForkJoinPool extends AbstractExecutorService {
public
boolean
isTerminated
()
{
public
boolean
isTerminated
()
{
long
c
=
ctl
;
long
c
=
ctl
;
return
((
c
&
STOP_BIT
)
!=
0L
&&
return
((
c
&
STOP_BIT
)
!=
0L
&&
(
short
)(
c
>>>
TC_SHIFT
)
==
-(
config
&
SMASK
)
);
(
short
)(
c
>>>
TC_SHIFT
)
+
parallelism
<=
0
);
}
}
/**
/**
...
@@ -3071,7 +2984,7 @@ public class ForkJoinPool extends AbstractExecutorService {
...
@@ -3071,7 +2984,7 @@ public class ForkJoinPool extends AbstractExecutorService {
public
boolean
isTerminating
()
{
public
boolean
isTerminating
()
{
long
c
=
ctl
;
long
c
=
ctl
;
return
((
c
&
STOP_BIT
)
!=
0L
&&
return
((
c
&
STOP_BIT
)
!=
0L
&&
(
short
)(
c
>>>
TC_SHIFT
)
!=
-(
config
&
SMASK
)
);
(
short
)(
c
>>>
TC_SHIFT
)
+
parallelism
>
0
);
}
}
/**
/**
...
@@ -3108,19 +3021,20 @@ public class ForkJoinPool extends AbstractExecutorService {
...
@@ -3108,19 +3021,20 @@ public class ForkJoinPool extends AbstractExecutorService {
long
nanos
=
unit
.
toNanos
(
timeout
);
long
nanos
=
unit
.
toNanos
(
timeout
);
if
(
isTerminated
())
if
(
isTerminated
())
return
true
;
return
true
;
long
startTime
=
System
.
nanoTime
();
if
(
nanos
<=
0L
)
boolean
terminated
=
false
;
return
false
;
long
deadline
=
System
.
nanoTime
()
+
nanos
;
synchronized
(
this
)
{
synchronized
(
this
)
{
for
(
long
waitTime
=
nanos
,
millis
=
0L
;;)
{
for
(;;)
{
if
(
terminated
=
isTerminated
()
||
if
(
isTerminated
())
waitTime
<=
0L
||
return
true
;
(
millis
=
unit
.
toMillis
(
waitTime
))
<=
0L
)
if
(
nanos
<=
0L
)
break
;
return
false
;
wait
(
millis
);
long
millis
=
TimeUnit
.
NANOSECONDS
.
toMillis
(
nanos
);
waitTime
=
nanos
-
(
System
.
nanoTime
()
-
startTime
);
wait
(
millis
>
0L
?
millis
:
1L
);
nanos
=
deadline
-
System
.
nanoTime
();
}
}
}
}
return
terminated
;
}
}
/**
/**
...
@@ -3159,11 +3073,8 @@ public class ForkJoinPool extends AbstractExecutorService {
...
@@ -3159,11 +3073,8 @@ public class ForkJoinPool extends AbstractExecutorService {
ForkJoinTask
<?>
t
;
WorkQueue
q
;
int
b
;
ForkJoinTask
<?>
t
;
WorkQueue
q
;
int
b
;
if
((
q
=
ws
[
r
++
&
m
])
!=
null
&&
(
b
=
q
.
base
)
-
q
.
top
<
0
)
{
if
((
q
=
ws
[
r
++
&
m
])
!=
null
&&
(
b
=
q
.
base
)
-
q
.
top
<
0
)
{
found
=
true
;
found
=
true
;
if
((
t
=
q
.
pollAt
(
b
))
!=
null
)
{
if
((
t
=
q
.
pollAt
(
b
))
!=
null
)
if
(
q
.
base
-
q
.
top
<
0
)
signalWork
(
q
);
t
.
doExec
();
t
.
doExec
();
}
break
;
break
;
}
}
}
}
...
@@ -3278,21 +3189,8 @@ public class ForkJoinPool extends AbstractExecutorService {
...
@@ -3278,21 +3189,8 @@ public class ForkJoinPool extends AbstractExecutorService {
Thread
t
=
Thread
.
currentThread
();
Thread
t
=
Thread
.
currentThread
();
if
(
t
instanceof
ForkJoinWorkerThread
)
{
if
(
t
instanceof
ForkJoinWorkerThread
)
{
ForkJoinPool
p
=
((
ForkJoinWorkerThread
)
t
).
pool
;
ForkJoinPool
p
=
((
ForkJoinWorkerThread
)
t
).
pool
;
while
(!
blocker
.
isReleasable
())
{
// variant of helpSignal
while
(!
blocker
.
isReleasable
())
{
WorkQueue
[]
ws
;
WorkQueue
q
;
int
m
,
u
;
if
(
p
.
tryCompensate
(
p
.
ctl
))
{
if
((
ws
=
p
.
workQueues
)
!=
null
&&
(
m
=
ws
.
length
-
1
)
>=
0
)
{
for
(
int
i
=
0
;
i
<=
m
;
++
i
)
{
if
(
blocker
.
isReleasable
())
return
;
if
((
q
=
ws
[
i
])
!=
null
&&
q
.
base
-
q
.
top
<
0
)
{
p
.
signalWork
(
q
);
if
((
u
=
(
int
)(
p
.
ctl
>>>
32
))
>=
0
||
(
u
>>
UAC_SHIFT
)
>=
0
)
break
;
}
}
}
if
(
p
.
tryCompensate
())
{
try
{
try
{
do
{}
while
(!
blocker
.
isReleasable
()
&&
do
{}
while
(!
blocker
.
isReleasable
()
&&
!
blocker
.
block
());
!
blocker
.
block
());
...
@@ -3330,6 +3228,7 @@ public class ForkJoinPool extends AbstractExecutorService {
...
@@ -3330,6 +3228,7 @@ public class ForkJoinPool extends AbstractExecutorService {
private
static
final
long
STEALCOUNT
;
private
static
final
long
STEALCOUNT
;
private
static
final
long
PLOCK
;
private
static
final
long
PLOCK
;
private
static
final
long
INDEXSEED
;
private
static
final
long
INDEXSEED
;
private
static
final
long
QBASE
;
private
static
final
long
QLOCK
;
private
static
final
long
QLOCK
;
static
{
static
{
...
@@ -3349,6 +3248,8 @@ public class ForkJoinPool extends AbstractExecutorService {
...
@@ -3349,6 +3248,8 @@ public class ForkJoinPool extends AbstractExecutorService {
PARKBLOCKER
=
U
.
objectFieldOffset
PARKBLOCKER
=
U
.
objectFieldOffset
(
tk
.
getDeclaredField
(
"parkBlocker"
));
(
tk
.
getDeclaredField
(
"parkBlocker"
));
Class
<?>
wk
=
WorkQueue
.
class
;
Class
<?>
wk
=
WorkQueue
.
class
;
QBASE
=
U
.
objectFieldOffset
(
wk
.
getDeclaredField
(
"base"
));
QLOCK
=
U
.
objectFieldOffset
QLOCK
=
U
.
objectFieldOffset
(
wk
.
getDeclaredField
(
"qlock"
));
(
wk
.
getDeclaredField
(
"qlock"
));
Class
<?>
ak
=
ForkJoinTask
[].
class
;
Class
<?>
ak
=
ForkJoinTask
[].
class
;
...
@@ -3368,7 +3269,7 @@ public class ForkJoinPool extends AbstractExecutorService {
...
@@ -3368,7 +3269,7 @@ public class ForkJoinPool extends AbstractExecutorService {
common
=
java
.
security
.
AccessController
.
doPrivileged
common
=
java
.
security
.
AccessController
.
doPrivileged
(
new
java
.
security
.
PrivilegedAction
<
ForkJoinPool
>()
{
(
new
java
.
security
.
PrivilegedAction
<
ForkJoinPool
>()
{
public
ForkJoinPool
run
()
{
return
makeCommonPool
();
}});
public
ForkJoinPool
run
()
{
return
makeCommonPool
();
}});
int
par
=
common
.
config
;
// report 1 even if threads disabled
int
par
=
common
.
parallelism
;
// report 1 even if threads disabled
commonParallelism
=
par
>
0
?
par
:
1
;
commonParallelism
=
par
>
0
?
par
:
1
;
}
}
...
@@ -3381,7 +3282,7 @@ public class ForkJoinPool extends AbstractExecutorService {
...
@@ -3381,7 +3282,7 @@ public class ForkJoinPool extends AbstractExecutorService {
ForkJoinWorkerThreadFactory
factory
ForkJoinWorkerThreadFactory
factory
=
defaultForkJoinWorkerThreadFactory
;
=
defaultForkJoinWorkerThreadFactory
;
UncaughtExceptionHandler
handler
=
null
;
UncaughtExceptionHandler
handler
=
null
;
try
{
// ignore exceptions in accesing/parsing properties
try
{
// ignore exceptions in acces
s
ing/parsing properties
String
pp
=
System
.
getProperty
String
pp
=
System
.
getProperty
(
"java.util.concurrent.ForkJoinPool.common.parallelism"
);
(
"java.util.concurrent.ForkJoinPool.common.parallelism"
);
String
fp
=
System
.
getProperty
String
fp
=
System
.
getProperty
...
@@ -3399,11 +3300,12 @@ public class ForkJoinPool extends AbstractExecutorService {
...
@@ -3399,11 +3300,12 @@ public class ForkJoinPool extends AbstractExecutorService {
}
catch
(
Exception
ignore
)
{
}
catch
(
Exception
ignore
)
{
}
}
if
(
parallelism
<
0
)
if
(
parallelism
<
0
&&
// default 1 less than #cores
parallelism
=
Runtime
.
getRuntime
().
availableProcessors
();
(
parallelism
=
Runtime
.
getRuntime
().
availableProcessors
()
-
1
)
<
0
)
parallelism
=
0
;
if
(
parallelism
>
MAX_CAP
)
if
(
parallelism
>
MAX_CAP
)
parallelism
=
MAX_CAP
;
parallelism
=
MAX_CAP
;
return
new
ForkJoinPool
(
parallelism
,
factory
,
handler
,
false
,
return
new
ForkJoinPool
(
parallelism
,
factory
,
handler
,
LIFO_QUEUE
,
"ForkJoinPool.commonPool-worker-"
);
"ForkJoinPool.commonPool-worker-"
);
}
}
...
...
src/share/classes/java/util/concurrent/ForkJoinTask.java
浏览文件 @
6693c900
...
@@ -165,7 +165,7 @@ import java.lang.reflect.Constructor;
...
@@ -165,7 +165,7 @@ import java.lang.reflect.Constructor;
* supports other methods and techniques (for example the use of
* supports other methods and techniques (for example the use of
* {@link Phaser}, {@link #helpQuiesce}, and {@link #complete}) that
* {@link Phaser}, {@link #helpQuiesce}, and {@link #complete}) that
* may be of use in constructing custom subclasses for problems that
* may be of use in constructing custom subclasses for problems that
* are not statically structured as DAGs. To support such usages a
* are not statically structured as DAGs. To support such usages
,
a
* ForkJoinTask may be atomically <em>tagged</em> with a {@code short}
* ForkJoinTask may be atomically <em>tagged</em> with a {@code short}
* value using {@link #setForkJoinTaskTag} or {@link
* value using {@link #setForkJoinTaskTag} or {@link
* #compareAndSetForkJoinTaskTag} and checked using {@link
* #compareAndSetForkJoinTaskTag} and checked using {@link
...
@@ -314,25 +314,35 @@ public abstract class ForkJoinTask<V> implements Future<V>, Serializable {
...
@@ -314,25 +314,35 @@ public abstract class ForkJoinTask<V> implements Future<V>, Serializable {
*/
*/
private
int
externalAwaitDone
()
{
private
int
externalAwaitDone
()
{
int
s
;
int
s
;
ForkJoinPool
.
externalHelpJoin
(
this
);
ForkJoinPool
cp
=
ForkJoinPool
.
common
;
boolean
interrupted
=
false
;
if
((
s
=
status
)
>=
0
)
{
while
((
s
=
status
)
>=
0
)
{
if
(
cp
!=
null
)
{
if
(
U
.
compareAndSwapInt
(
this
,
STATUS
,
s
,
s
|
SIGNAL
))
{
if
(
this
instanceof
CountedCompleter
)
synchronized
(
this
)
{
s
=
cp
.
externalHelpComplete
((
CountedCompleter
<?>)
this
,
Integer
.
MAX_VALUE
);
if
(
status
>=
0
)
{
else
if
(
cp
.
tryExternalUnpush
(
this
))
try
{
s
=
doExec
();
wait
();
}
}
catch
(
InterruptedException
ie
)
{
if
(
s
>=
0
&&
(
s
=
status
)
>=
0
)
{
interrupted
=
true
;
boolean
interrupted
=
false
;
do
{
if
(
U
.
compareAndSwapInt
(
this
,
STATUS
,
s
,
s
|
SIGNAL
))
{
synchronized
(
this
)
{
if
(
status
>=
0
)
{
try
{
wait
();
}
catch
(
InterruptedException
ie
)
{
interrupted
=
true
;
}
}
else
notifyAll
();
}
}
}
}
else
}
while
((
s
=
status
)
>=
0
);
notifyAll
();
if
(
interrupted
)
}
Thread
.
currentThread
().
interrupt
();
}
}
}
}
if
(
interrupted
)
Thread
.
currentThread
().
interrupt
();
return
s
;
return
s
;
}
}
...
@@ -341,9 +351,15 @@ public abstract class ForkJoinTask<V> implements Future<V>, Serializable {
...
@@ -341,9 +351,15 @@ public abstract class ForkJoinTask<V> implements Future<V>, Serializable {
*/
*/
private
int
externalInterruptibleAwaitDone
()
throws
InterruptedException
{
private
int
externalInterruptibleAwaitDone
()
throws
InterruptedException
{
int
s
;
int
s
;
ForkJoinPool
cp
=
ForkJoinPool
.
common
;
if
(
Thread
.
interrupted
())
if
(
Thread
.
interrupted
())
throw
new
InterruptedException
();
throw
new
InterruptedException
();
ForkJoinPool
.
externalHelpJoin
(
this
);
if
((
s
=
status
)
>=
0
&&
cp
!=
null
)
{
if
(
this
instanceof
CountedCompleter
)
cp
.
externalHelpComplete
((
CountedCompleter
<?>)
this
,
Integer
.
MAX_VALUE
);
else
if
(
cp
.
tryExternalUnpush
(
this
))
doExec
();
}
while
((
s
=
status
)
>=
0
)
{
while
((
s
=
status
)
>=
0
)
{
if
(
U
.
compareAndSwapInt
(
this
,
STATUS
,
s
,
s
|
SIGNAL
))
{
if
(
U
.
compareAndSwapInt
(
this
,
STATUS
,
s
,
s
|
SIGNAL
))
{
synchronized
(
this
)
{
synchronized
(
this
)
{
...
@@ -357,7 +373,6 @@ public abstract class ForkJoinTask<V> implements Future<V>, Serializable {
...
@@ -357,7 +373,6 @@ public abstract class ForkJoinTask<V> implements Future<V>, Serializable {
return
s
;
return
s
;
}
}
/**
/**
* Implementation for join, get, quietlyJoin. Directly handles
* Implementation for join, get, quietlyJoin. Directly handles
* only cases of already-completed, external wait, and
* only cases of already-completed, external wait, and
...
@@ -629,14 +644,9 @@ public abstract class ForkJoinTask<V> implements Future<V>, Serializable {
...
@@ -629,14 +644,9 @@ public abstract class ForkJoinTask<V> implements Future<V>, Serializable {
/**
/**
* A version of "sneaky throw" to relay exceptions
* A version of "sneaky throw" to relay exceptions
*/
*/
static
void
rethrow
(
final
Throwable
ex
)
{
static
void
rethrow
(
Throwable
ex
)
{
if
(
ex
!=
null
)
{
if
(
ex
!=
null
)
if
(
ex
instanceof
Error
)
throw
(
Error
)
ex
;
if
(
ex
instanceof
RuntimeException
)
throw
(
RuntimeException
)
ex
;
ForkJoinTask
.<
RuntimeException
>
uncheckedThrow
(
ex
);
ForkJoinTask
.<
RuntimeException
>
uncheckedThrow
(
ex
);
}
}
}
/**
/**
...
@@ -646,8 +656,7 @@ public abstract class ForkJoinTask<V> implements Future<V>, Serializable {
...
@@ -646,8 +656,7 @@ public abstract class ForkJoinTask<V> implements Future<V>, Serializable {
*/
*/
@SuppressWarnings
(
"unchecked"
)
static
<
T
extends
Throwable
>
@SuppressWarnings
(
"unchecked"
)
static
<
T
extends
Throwable
>
void
uncheckedThrow
(
Throwable
t
)
throws
T
{
void
uncheckedThrow
(
Throwable
t
)
throws
T
{
if
(
t
!=
null
)
throw
(
T
)
t
;
// rely on vacuous cast
throw
(
T
)
t
;
// rely on vacuous cast
}
}
/**
/**
...
@@ -1010,6 +1019,7 @@ public abstract class ForkJoinTask<V> implements Future<V>, Serializable {
...
@@ -1010,6 +1019,7 @@ public abstract class ForkJoinTask<V> implements Future<V>, Serializable {
// Messy in part because we measure in nanosecs, but wait in millisecs
// Messy in part because we measure in nanosecs, but wait in millisecs
int
s
;
long
ms
;
int
s
;
long
ms
;
long
ns
=
unit
.
toNanos
(
timeout
);
long
ns
=
unit
.
toNanos
(
timeout
);
ForkJoinPool
cp
;
if
((
s
=
status
)
>=
0
&&
ns
>
0L
)
{
if
((
s
=
status
)
>=
0
&&
ns
>
0L
)
{
long
deadline
=
System
.
nanoTime
()
+
ns
;
long
deadline
=
System
.
nanoTime
()
+
ns
;
ForkJoinPool
p
=
null
;
ForkJoinPool
p
=
null
;
...
@@ -1021,8 +1031,12 @@ public abstract class ForkJoinTask<V> implements Future<V>, Serializable {
...
@@ -1021,8 +1031,12 @@ public abstract class ForkJoinTask<V> implements Future<V>, Serializable {
w
=
wt
.
workQueue
;
w
=
wt
.
workQueue
;
p
.
helpJoinOnce
(
w
,
this
);
// no retries on failure
p
.
helpJoinOnce
(
w
,
this
);
// no retries on failure
}
}
else
else
if
((
cp
=
ForkJoinPool
.
common
)
!=
null
)
{
ForkJoinPool
.
externalHelpJoin
(
this
);
if
(
this
instanceof
CountedCompleter
)
cp
.
externalHelpComplete
((
CountedCompleter
<?>)
this
,
Integer
.
MAX_VALUE
);
else
if
(
cp
.
tryExternalUnpush
(
this
))
doExec
();
}
boolean
canBlock
=
false
;
boolean
canBlock
=
false
;
boolean
interrupted
=
false
;
boolean
interrupted
=
false
;
try
{
try
{
...
@@ -1030,7 +1044,7 @@ public abstract class ForkJoinTask<V> implements Future<V>, Serializable {
...
@@ -1030,7 +1044,7 @@ public abstract class ForkJoinTask<V> implements Future<V>, Serializable {
if
(
w
!=
null
&&
w
.
qlock
<
0
)
if
(
w
!=
null
&&
w
.
qlock
<
0
)
cancelIgnoringExceptions
(
this
);
cancelIgnoringExceptions
(
this
);
else
if
(!
canBlock
)
{
else
if
(!
canBlock
)
{
if
(
p
==
null
||
p
.
tryCompensate
())
if
(
p
==
null
||
p
.
tryCompensate
(
p
.
ctl
))
canBlock
=
true
;
canBlock
=
true
;
}
}
else
{
else
{
...
@@ -1171,7 +1185,7 @@ public abstract class ForkJoinTask<V> implements Future<V>, Serializable {
...
@@ -1171,7 +1185,7 @@ public abstract class ForkJoinTask<V> implements Future<V>, Serializable {
Thread
t
;
Thread
t
;
return
(((
t
=
Thread
.
currentThread
())
instanceof
ForkJoinWorkerThread
)
?
return
(((
t
=
Thread
.
currentThread
())
instanceof
ForkJoinWorkerThread
)
?
((
ForkJoinWorkerThread
)
t
).
workQueue
.
tryUnpush
(
this
)
:
((
ForkJoinWorkerThread
)
t
).
workQueue
.
tryUnpush
(
this
)
:
ForkJoinPool
.
tryExternalUnpush
(
this
));
ForkJoinPool
.
common
.
tryExternalUnpush
(
this
));
}
}
/**
/**
...
@@ -1340,7 +1354,7 @@ public abstract class ForkJoinTask<V> implements Future<V>, Serializable {
...
@@ -1340,7 +1354,7 @@ public abstract class ForkJoinTask<V> implements Future<V>, Serializable {
*
*
* @param e the expected tag value
* @param e the expected tag value
* @param tag the new tag value
* @param tag the new tag value
* @return
true
if successful; i.e., the current value was
* @return
{@code true}
if successful; i.e., the current value was
* equal to e and is now tag.
* equal to e and is now tag.
* @since 1.8
* @since 1.8
*/
*/
...
...
src/share/classes/java/util/concurrent/ForkJoinWorkerThread.java
浏览文件 @
6693c900
...
@@ -43,8 +43,8 @@ package java.util.concurrent;
...
@@ -43,8 +43,8 @@ package java.util.concurrent;
* scheduling or execution. However, you can override initialization
* scheduling or execution. However, you can override initialization
* and termination methods surrounding the main task processing loop.
* and termination methods surrounding the main task processing loop.
* If you do create such a subclass, you will also need to supply a
* If you do create such a subclass, you will also need to supply a
* custom {@link ForkJoinPool.ForkJoinWorkerThreadFactory} to
use it
* custom {@link ForkJoinPool.ForkJoinWorkerThreadFactory} to
* in a {@code ForkJoinPool}.
*
{@linkplain ForkJoinPool#ForkJoinPool use it}
in a {@code ForkJoinPool}.
*
*
* @since 1.7
* @since 1.7
* @author Doug Lea
* @author Doug Lea
...
@@ -89,16 +89,17 @@ public class ForkJoinWorkerThread extends Thread {
...
@@ -89,16 +89,17 @@ public class ForkJoinWorkerThread extends Thread {
}
}
/**
/**
* Returns the index number of this thread in its pool. The
* Returns the unique index number of this thread in its pool.
* returned value ranges from zero to the maximum number of
* The returned value ranges from zero to the maximum number of
* threads (minus one) that have ever been created in the pool.
* threads (minus one) that may exist in the pool, and does not
* This method may be useful for applications that track status or
* change during the lifetime of the thread. This method may be
* collect results per-worker rather than per-task.
* useful for applications that track status or collect results
* per-worker-thread rather than per-task.
*
*
* @return the index number
* @return the index number
*/
*/
public
int
getPoolIndex
()
{
public
int
getPoolIndex
()
{
return
workQueue
.
poolIndex
;
return
workQueue
.
poolIndex
>>>
1
;
// ignore odd/even tag bit
}
}
/**
/**
...
...
src/share/classes/java/util/concurrent/Future.java
浏览文件 @
6693c900
...
@@ -36,19 +36,19 @@
...
@@ -36,19 +36,19 @@
package
java.util.concurrent
;
package
java.util.concurrent
;
/**
/**
* A
<tt>Future</tt>
represents the result of an asynchronous
* A
{@code Future}
represents the result of an asynchronous
* computation. Methods are provided to check if the computation is
* computation. Methods are provided to check if the computation is
* complete, to wait for its completion, and to retrieve the result of
* complete, to wait for its completion, and to retrieve the result of
* the computation. The result can only be retrieved using method
* the computation. The result can only be retrieved using method
*
<tt>get</tt>
when the computation has completed, blocking if
*
{@code get}
when the computation has completed, blocking if
* necessary until it is ready. Cancellation is performed by the
* necessary until it is ready. Cancellation is performed by the
*
<tt>cancel</tt>
method. Additional methods are provided to
*
{@code cancel}
method. Additional methods are provided to
* determine if the task completed normally or was cancelled. Once a
* determine if the task completed normally or was cancelled. Once a
* computation has completed, the computation cannot be cancelled.
* computation has completed, the computation cannot be cancelled.
* If you would like to use a
<tt>Future</tt>
for the sake
* If you would like to use a
{@code Future}
for the sake
* of cancellability but not provide a usable result, you can
* of cancellability but not provide a usable result, you can
* declare types of the form {@code Future<?>} and
* declare types of the form {@code Future<?>} and
* return
<tt>null</tt>
as a result of the underlying task.
* return
{@code null}
as a result of the underlying task.
*
*
* <p>
* <p>
* <b>Sample Usage</b> (Note that the following classes are all
* <b>Sample Usage</b> (Note that the following classes are all
...
@@ -72,9 +72,9 @@ package java.util.concurrent;
...
@@ -72,9 +72,9 @@ package java.util.concurrent;
* }
* }
* }}</pre>
* }}</pre>
*
*
* The {@link FutureTask} class is an implementation of
<tt>Future</tt>
that
* The {@link FutureTask} class is an implementation of
{@code Future}
that
* implements
<tt>Runnable</tt>, and so may be executed by an <tt>Executor</tt>
.
* implements
{@code Runnable}, and so may be executed by an {@code Executor}
.
* For example, the above construction with
<tt>submit</tt>
could be replaced by:
* For example, the above construction with
{@code submit}
could be replaced by:
* <pre> {@code
* <pre> {@code
* FutureTask<String> future =
* FutureTask<String> future =
* new FutureTask<String>(new Callable<String>() {
* new FutureTask<String>(new Callable<String>() {
...
@@ -91,7 +91,7 @@ package java.util.concurrent;
...
@@ -91,7 +91,7 @@ package java.util.concurrent;
* @see Executor
* @see Executor
* @since 1.5
* @since 1.5
* @author Doug Lea
* @author Doug Lea
* @param <V> The result type returned by this Future's
<tt>get</tt>
method
* @param <V> The result type returned by this Future's
{@code get}
method
*/
*/
public
interface
Future
<
V
>
{
public
interface
Future
<
V
>
{
...
@@ -99,41 +99,41 @@ public interface Future<V> {
...
@@ -99,41 +99,41 @@ public interface Future<V> {
* Attempts to cancel execution of this task. This attempt will
* Attempts to cancel execution of this task. This attempt will
* fail if the task has already completed, has already been cancelled,
* fail if the task has already completed, has already been cancelled,
* or could not be cancelled for some other reason. If successful,
* or could not be cancelled for some other reason. If successful,
* and this task has not started when
<tt>cancel</tt>
is called,
* and this task has not started when
{@code cancel}
is called,
* this task should never run. If the task has already started,
* this task should never run. If the task has already started,
* then the
<tt>mayInterruptIfRunning</tt>
parameter determines
* then the
{@code mayInterruptIfRunning}
parameter determines
* whether the thread executing this task should be interrupted in
* whether the thread executing this task should be interrupted in
* an attempt to stop the task.
* an attempt to stop the task.
*
*
* <p>After this method returns, subsequent calls to {@link #isDone} will
* <p>After this method returns, subsequent calls to {@link #isDone} will
* always return
<tt>true</tt>
. Subsequent calls to {@link #isCancelled}
* always return
{@code true}
. Subsequent calls to {@link #isCancelled}
* will always return
<tt>true</tt> if this method returned <tt>true</tt>
.
* will always return
{@code true} if this method returned {@code true}
.
*
*
* @param mayInterruptIfRunning
<tt>true</tt>
if the thread executing this
* @param mayInterruptIfRunning
{@code true}
if the thread executing this
* task should be interrupted; otherwise, in-progress tasks are allowed
* task should be interrupted; otherwise, in-progress tasks are allowed
* to complete
* to complete
* @return
<tt>false</tt>
if the task could not be cancelled,
* @return
{@code false}
if the task could not be cancelled,
* typically because it has already completed normally;
* typically because it has already completed normally;
*
<tt>true</tt>
otherwise
*
{@code true}
otherwise
*/
*/
boolean
cancel
(
boolean
mayInterruptIfRunning
);
boolean
cancel
(
boolean
mayInterruptIfRunning
);
/**
/**
* Returns
<tt>true</tt>
if this task was cancelled before it completed
* Returns
{@code true}
if this task was cancelled before it completed
* normally.
* normally.
*
*
* @return
<tt>true</tt>
if this task was cancelled before it completed
* @return
{@code true}
if this task was cancelled before it completed
*/
*/
boolean
isCancelled
();
boolean
isCancelled
();
/**
/**
* Returns
<tt>true</tt>
if this task completed.
* Returns
{@code true}
if this task completed.
*
*
* Completion may be due to normal termination, an exception, or
* Completion may be due to normal termination, an exception, or
* cancellation -- in all of these cases, this method will return
* cancellation -- in all of these cases, this method will return
*
<tt>true</tt>
.
*
{@code true}
.
*
*
* @return
<tt>true</tt>
if this task completed
* @return
{@code true}
if this task completed
*/
*/
boolean
isDone
();
boolean
isDone
();
...
...
src/share/classes/java/util/concurrent/FutureTask.java
浏览文件 @
6693c900
...
@@ -162,19 +162,23 @@ public class FutureTask<V> implements RunnableFuture<V> {
...
@@ -162,19 +162,23 @@ public class FutureTask<V> implements RunnableFuture<V> {
}
}
public
boolean
cancel
(
boolean
mayInterruptIfRunning
)
{
public
boolean
cancel
(
boolean
mayInterruptIfRunning
)
{
if
(
state
!=
NEW
)
if
(!(
state
==
NEW
&&
UNSAFE
.
compareAndSwapInt
(
this
,
stateOffset
,
NEW
,
mayInterruptIfRunning
?
INTERRUPTING
:
CANCELLED
)))
return
false
;
return
false
;
if
(
mayInterruptIfRunning
)
{
try
{
// in case call to interrupt throws exception
if
(!
UNSAFE
.
compareAndSwapInt
(
this
,
stateOffset
,
NEW
,
INTERRUPTING
))
if
(
mayInterruptIfRunning
)
{
return
false
;
try
{
Thread
t
=
runner
;
Thread
t
=
runner
;
if
(
t
!=
null
)
if
(
t
!=
null
)
t
.
interrupt
();
t
.
interrupt
();
UNSAFE
.
putOrderedInt
(
this
,
stateOffset
,
INTERRUPTED
);
// final state
}
finally
{
// final state
UNSAFE
.
putOrderedInt
(
this
,
stateOffset
,
INTERRUPTED
);
}
}
}
finally
{
finishCompletion
();
}
}
else
if
(!
UNSAFE
.
compareAndSwapInt
(
this
,
stateOffset
,
NEW
,
CANCELLED
))
return
false
;
finishCompletion
();
return
true
;
return
true
;
}
}
...
@@ -288,7 +292,7 @@ public class FutureTask<V> implements RunnableFuture<V> {
...
@@ -288,7 +292,7 @@ public class FutureTask<V> implements RunnableFuture<V> {
* designed for use with tasks that intrinsically execute more
* designed for use with tasks that intrinsically execute more
* than once.
* than once.
*
*
* @return
true
if successfully run and reset
* @return
{@code true}
if successfully run and reset
*/
*/
protected
boolean
runAndReset
()
{
protected
boolean
runAndReset
()
{
if
(
state
!=
NEW
||
if
(
state
!=
NEW
||
...
...
src/share/classes/java/util/concurrent/RecursiveAction.java
浏览文件 @
6693c900
...
@@ -63,7 +63,7 @@ package java.util.concurrent;
...
@@ -63,7 +63,7 @@ package java.util.concurrent;
* }
* }
* }
* }
* // implementation details follow:
* // implementation details follow:
*
final static
int THRESHOLD = 1000;
*
static final
int THRESHOLD = 1000;
* void sortSequentially(int lo, int hi) {
* void sortSequentially(int lo, int hi) {
* Arrays.sort(array, lo, hi);
* Arrays.sort(array, lo, hi);
* }
* }
...
@@ -140,21 +140,21 @@ package java.util.concurrent;
...
@@ -140,21 +140,21 @@ package java.util.concurrent;
* int h = hi;
* int h = hi;
* Applyer right = null;
* Applyer right = null;
* while (h - l > 1 && getSurplusQueuedTaskCount() <= 3) {
* while (h - l > 1 && getSurplusQueuedTaskCount() <= 3) {
*
int mid = (l + h) >>> 1;
* int mid = (l + h) >>> 1;
*
right = new Applyer(array, mid, h, right);
* right = new Applyer(array, mid, h, right);
*
right.fork();
* right.fork();
*
h = mid;
* h = mid;
* }
* }
* double sum = atLeaf(l, h);
* double sum = atLeaf(l, h);
* while (right != null) {
* while (right != null) {
*
if (right.tryUnfork()) // directly calculate if not stolen
* if (right.tryUnfork()) // directly calculate if not stolen
*
sum += right.atLeaf(right.lo, right.hi);
* sum += right.atLeaf(right.lo, right.hi);
* else {
* else {
*
right.join();
* right.join();
*
sum += right.result;
* sum += right.result;
*
}
* }
*
right = right.next;
* right = right.next;
*
}
* }
* result = sum;
* result = sum;
* }
* }
* }}</pre>
* }}</pre>
...
...
src/share/classes/java/util/concurrent/RecursiveTask.java
浏览文件 @
6693c900
...
@@ -46,7 +46,7 @@ package java.util.concurrent;
...
@@ -46,7 +46,7 @@ package java.util.concurrent;
* Fibonacci(int n) { this.n = n; }
* Fibonacci(int n) { this.n = n; }
* Integer compute() {
* Integer compute() {
* if (n <= 1)
* if (n <= 1)
*
return n;
* return n;
* Fibonacci f1 = new Fibonacci(n - 1);
* Fibonacci f1 = new Fibonacci(n - 1);
* f1.fork();
* f1.fork();
* Fibonacci f2 = new Fibonacci(n - 2);
* Fibonacci f2 = new Fibonacci(n - 2);
...
@@ -75,6 +75,7 @@ public abstract class RecursiveTask<V> extends ForkJoinTask<V> {
...
@@ -75,6 +75,7 @@ public abstract class RecursiveTask<V> extends ForkJoinTask<V> {
/**
/**
* The main computation performed by this task.
* The main computation performed by this task.
* @return the result of the computation
*/
*/
protected
abstract
V
compute
();
protected
abstract
V
compute
();
...
...
src/share/classes/java/util/concurrent/RejectedExecutionException.java
浏览文件 @
6693c900
...
@@ -46,14 +46,14 @@ public class RejectedExecutionException extends RuntimeException {
...
@@ -46,14 +46,14 @@ public class RejectedExecutionException extends RuntimeException {
private
static
final
long
serialVersionUID
=
-
375805702767069545L
;
private
static
final
long
serialVersionUID
=
-
375805702767069545L
;
/**
/**
* Constructs a
<tt>RejectedExecutionException</tt>
with no detail message.
* Constructs a
{@code RejectedExecutionException}
with no detail message.
* The cause is not initialized, and may subsequently be
* The cause is not initialized, and may subsequently be
* initialized by a call to {@link #initCause(Throwable) initCause}.
* initialized by a call to {@link #initCause(Throwable) initCause}.
*/
*/
public
RejectedExecutionException
()
{
}
public
RejectedExecutionException
()
{
}
/**
/**
* Constructs a
<tt>RejectedExecutionException</tt>
with the
* Constructs a
{@code RejectedExecutionException}
with the
* specified detail message. The cause is not initialized, and may
* specified detail message. The cause is not initialized, and may
* subsequently be initialized by a call to {@link
* subsequently be initialized by a call to {@link
* #initCause(Throwable) initCause}.
* #initCause(Throwable) initCause}.
...
@@ -65,7 +65,7 @@ public class RejectedExecutionException extends RuntimeException {
...
@@ -65,7 +65,7 @@ public class RejectedExecutionException extends RuntimeException {
}
}
/**
/**
* Constructs a
<tt>RejectedExecutionException</tt>
with the
* Constructs a
{@code RejectedExecutionException}
with the
* specified detail message and cause.
* specified detail message and cause.
*
*
* @param message the detail message
* @param message the detail message
...
@@ -77,10 +77,10 @@ public class RejectedExecutionException extends RuntimeException {
...
@@ -77,10 +77,10 @@ public class RejectedExecutionException extends RuntimeException {
}
}
/**
/**
* Constructs a
<tt>RejectedExecutionException</tt>
with the
* Constructs a
{@code RejectedExecutionException}
with the
* specified cause. The detail message is set to {@code (cause ==
* specified cause. The detail message is set to {@code (cause ==
* null ? null : cause.toString())} (which typically contains
* null ? null : cause.toString())} (which typically contains
* the class and detail message of
<tt>cause</tt>
).
* the class and detail message of
{@code cause}
).
*
*
* @param cause the cause (which is saved for later retrieval by the
* @param cause the cause (which is saved for later retrieval by the
* {@link #getCause()} method)
* {@link #getCause()} method)
...
...
src/share/classes/java/util/concurrent/RunnableFuture.java
浏览文件 @
6693c900
...
@@ -37,13 +37,13 @@ package java.util.concurrent;
...
@@ -37,13 +37,13 @@ package java.util.concurrent;
/**
/**
* A {@link Future} that is {@link Runnable}. Successful execution of
* A {@link Future} that is {@link Runnable}. Successful execution of
* the
<tt>run</tt> method causes completion of the <tt>Future</tt>
* the
{@code run} method causes completion of the {@code Future}
* and allows access to its results.
* and allows access to its results.
* @see FutureTask
* @see FutureTask
* @see Executor
* @see Executor
* @since 1.6
* @since 1.6
* @author Doug Lea
* @author Doug Lea
* @param <V> The result type returned by this Future's
<tt>get</tt>
method
* @param <V> The result type returned by this Future's
{@code get}
method
*/
*/
public
interface
RunnableFuture
<
V
>
extends
Runnable
,
Future
<
V
>
{
public
interface
RunnableFuture
<
V
>
extends
Runnable
,
Future
<
V
>
{
/**
/**
...
...
src/share/classes/java/util/concurrent/RunnableScheduledFuture.java
浏览文件 @
6693c900
...
@@ -37,22 +37,22 @@ package java.util.concurrent;
...
@@ -37,22 +37,22 @@ package java.util.concurrent;
/**
/**
* A {@link ScheduledFuture} that is {@link Runnable}. Successful
* A {@link ScheduledFuture} that is {@link Runnable}. Successful
* execution of the
<tt>run</tt>
method causes completion of the
* execution of the
{@code run}
method causes completion of the
*
<tt>Future</tt>
and allows access to its results.
*
{@code Future}
and allows access to its results.
* @see FutureTask
* @see FutureTask
* @see Executor
* @see Executor
* @since 1.6
* @since 1.6
* @author Doug Lea
* @author Doug Lea
* @param <V> The result type returned by this Future's
<tt>get</tt>
method
* @param <V> The result type returned by this Future's
{@code get}
method
*/
*/
public
interface
RunnableScheduledFuture
<
V
>
extends
RunnableFuture
<
V
>,
ScheduledFuture
<
V
>
{
public
interface
RunnableScheduledFuture
<
V
>
extends
RunnableFuture
<
V
>,
ScheduledFuture
<
V
>
{
/**
/**
* Returns
true if this is a periodic task
. A periodic task may
* Returns
{@code true} if this task is periodic
. A periodic task may
* re-run according to some schedule. A non-periodic task can be
* re-run according to some schedule. A non-periodic task can be
* run only once.
* run only once.
*
*
* @return
true
if this task is periodic
* @return
{@code true}
if this task is periodic
*/
*/
boolean
isPeriodic
();
boolean
isPeriodic
();
}
}
src/share/classes/java/util/concurrent/ScheduledExecutorService.java
浏览文件 @
6693c900
...
@@ -39,30 +39,30 @@ package java.util.concurrent;
...
@@ -39,30 +39,30 @@ package java.util.concurrent;
* An {@link ExecutorService} that can schedule commands to run after a given
* An {@link ExecutorService} that can schedule commands to run after a given
* delay, or to execute periodically.
* delay, or to execute periodically.
*
*
* <p>
The <tt>schedule</tt>
methods create tasks with various delays
* <p>
The {@code schedule}
methods create tasks with various delays
* and return a task object that can be used to cancel or check
* and return a task object that can be used to cancel or check
* execution. The
<tt>scheduleAtFixedRate</tt>
and
* execution. The
{@code scheduleAtFixedRate}
and
*
<tt>scheduleWithFixedDelay</tt>
methods create and execute tasks
*
{@code scheduleWithFixedDelay}
methods create and execute tasks
* that run periodically until cancelled.
* that run periodically until cancelled.
*
*
* <p>
Commands submitted using the {@link Executor#execute} and
* <p>
Commands submitted using the {@link Executor#execute(Runnable)}
*
{@link ExecutorService} <tt>submit</tt> methods are scheduled with
*
and {@link ExecutorService} {@code submit} methods are scheduled
* a requested delay of zero. Zero and negative delays (but not
*
with
a requested delay of zero. Zero and negative delays (but not
* periods) are also allowed in
<tt>schedule</tt>
methods, and are
* periods) are also allowed in
{@code schedule}
methods, and are
* treated as requests for immediate execution.
* treated as requests for immediate execution.
*
*
* <p>All
<tt>schedule</tt>
methods accept <em>relative</em> delays and
* <p>All
{@code schedule}
methods accept <em>relative</em> delays and
* periods as arguments, not absolute times or dates. It is a simple
* periods as arguments, not absolute times or dates. It is a simple
* matter to transform an absolute time represented as a {@link
* matter to transform an absolute time represented as a {@link
* java.util.Date} to the required form. For example, to schedule at
* java.util.Date} to the required form. For example, to schedule at
* a certain future
<tt>date</tt>, you can use: <tt>
schedule(task,
* a certain future
{@code date}, you can use: {@code
schedule(task,
* date.getTime() - System.currentTimeMillis(),
* date.getTime() - System.currentTimeMillis(),
* TimeUnit.MILLISECONDS)
</tt>
. Beware however that expiration of a
* TimeUnit.MILLISECONDS)
}
. Beware however that expiration of a
* relative delay need not coincide with the current
<tt>Date</tt>
at
* relative delay need not coincide with the current
{@code Date}
at
* which the task is enabled due to network time synchronization
* which the task is enabled due to network time synchronization
* protocols, clock drift, or other factors.
* protocols, clock drift, or other factors.
*
*
* The {@link Executors} class provides convenient factory methods for
*
<p>
The {@link Executors} class provides convenient factory methods for
* the ScheduledExecutorService implementations provided in this package.
* the ScheduledExecutorService implementations provided in this package.
*
*
* <h3>Usage Example</h3>
* <h3>Usage Example</h3>
...
@@ -101,8 +101,8 @@ public interface ScheduledExecutorService extends ExecutorService {
...
@@ -101,8 +101,8 @@ public interface ScheduledExecutorService extends ExecutorService {
* @param delay the time from now to delay execution
* @param delay the time from now to delay execution
* @param unit the time unit of the delay parameter
* @param unit the time unit of the delay parameter
* @return a ScheduledFuture representing pending completion of
* @return a ScheduledFuture representing pending completion of
* the task and whose
<tt>get()</tt>
method will return
* the task and whose
{@code get()}
method will return
*
<tt>null</tt>
upon completion
*
{@code null}
upon completion
* @throws RejectedExecutionException if the task cannot be
* @throws RejectedExecutionException if the task cannot be
* scheduled for execution
* scheduled for execution
* @throws NullPointerException if command is null
* @throws NullPointerException if command is null
...
@@ -129,8 +129,8 @@ public interface ScheduledExecutorService extends ExecutorService {
...
@@ -129,8 +129,8 @@ public interface ScheduledExecutorService extends ExecutorService {
* Creates and executes a periodic action that becomes enabled first
* Creates and executes a periodic action that becomes enabled first
* after the given initial delay, and subsequently with the given
* after the given initial delay, and subsequently with the given
* period; that is executions will commence after
* period; that is executions will commence after
*
<tt>initialDelay</tt> then <tt>initialDelay+period</tt>
, then
*
{@code initialDelay} then {@code initialDelay+period}
, then
*
<tt>initialDelay + 2 * period</tt>
, and so on.
*
{@code initialDelay + 2 * period}
, and so on.
* If any execution of the task
* If any execution of the task
* encounters an exception, subsequent executions are suppressed.
* encounters an exception, subsequent executions are suppressed.
* Otherwise, the task will only terminate via cancellation or
* Otherwise, the task will only terminate via cancellation or
...
@@ -143,7 +143,7 @@ public interface ScheduledExecutorService extends ExecutorService {
...
@@ -143,7 +143,7 @@ public interface ScheduledExecutorService extends ExecutorService {
* @param period the period between successive executions
* @param period the period between successive executions
* @param unit the time unit of the initialDelay and period parameters
* @param unit the time unit of the initialDelay and period parameters
* @return a ScheduledFuture representing pending completion of
* @return a ScheduledFuture representing pending completion of
* the task, and whose
<tt>get()</tt>
method will throw an
* the task, and whose
{@code get()}
method will throw an
* exception upon cancellation
* exception upon cancellation
* @throws RejectedExecutionException if the task cannot be
* @throws RejectedExecutionException if the task cannot be
* scheduled for execution
* scheduled for execution
...
@@ -170,7 +170,7 @@ public interface ScheduledExecutorService extends ExecutorService {
...
@@ -170,7 +170,7 @@ public interface ScheduledExecutorService extends ExecutorService {
* execution and the commencement of the next
* execution and the commencement of the next
* @param unit the time unit of the initialDelay and delay parameters
* @param unit the time unit of the initialDelay and delay parameters
* @return a ScheduledFuture representing pending completion of
* @return a ScheduledFuture representing pending completion of
* the task, and whose
<tt>get()</tt>
method will throw an
* the task, and whose
{@code get()}
method will throw an
* exception upon cancellation
* exception upon cancellation
* @throws RejectedExecutionException if the task cannot be
* @throws RejectedExecutionException if the task cannot be
* scheduled for execution
* scheduled for execution
...
...
src/share/classes/java/util/concurrent/ScheduledThreadPoolExecutor.java
浏览文件 @
6693c900
...
@@ -81,7 +81,7 @@ import java.util.*;
...
@@ -81,7 +81,7 @@ import java.util.*;
* without threads to handle tasks once they become eligible to run.
* without threads to handle tasks once they become eligible to run.
*
*
* <p><b>Extension notes:</b> This class overrides the
* <p><b>Extension notes:</b> This class overrides the
* {@link ThreadPoolExecutor#execute execute} and
* {@link ThreadPoolExecutor#execute
(Runnable)
execute} and
* {@link AbstractExecutorService#submit(Runnable) submit}
* {@link AbstractExecutorService#submit(Runnable) submit}
* methods to generate internal {@link ScheduledFuture} objects to
* methods to generate internal {@link ScheduledFuture} objects to
* control per-task delays and scheduling. To preserve
* control per-task delays and scheduling. To preserve
...
@@ -256,9 +256,9 @@ public class ScheduledThreadPoolExecutor
...
@@ -256,9 +256,9 @@ public class ScheduledThreadPoolExecutor
}
}
/**
/**
* Returns
true
if this is a periodic (not a one-shot) action.
* Returns
{@code true}
if this is a periodic (not a one-shot) action.
*
*
* @return
true
if periodic
* @return
{@code true}
if periodic
*/
*/
public
boolean
isPeriodic
()
{
public
boolean
isPeriodic
()
{
return
period
!=
0
;
return
period
!=
0
;
...
@@ -315,7 +315,7 @@ public class ScheduledThreadPoolExecutor
...
@@ -315,7 +315,7 @@ public class ScheduledThreadPoolExecutor
* is shut down, rejects the task. Otherwise adds task to queue
* is shut down, rejects the task. Otherwise adds task to queue
* and starts a thread, if necessary, to run it. (We cannot
* and starts a thread, if necessary, to run it. (We cannot
* prestart the thread to run the task because the task (probably)
* prestart the thread to run the task because the task (probably)
* shouldn't be run yet
,)
If the pool is shut down while the task
* shouldn't be run yet
.)
If the pool is shut down while the task
* is being added, cancel and remove it if required by state and
* is being added, cancel and remove it if required by state and
* run-after-shutdown parameters.
* run-after-shutdown parameters.
*
*
...
@@ -654,7 +654,7 @@ public class ScheduledThreadPoolExecutor
...
@@ -654,7 +654,7 @@ public class ScheduledThreadPoolExecutor
* {@code false} when already shutdown.
* {@code false} when already shutdown.
* This value is by default {@code false}.
* This value is by default {@code false}.
*
*
* @param value if {@code true}, continue after shutdown, else don't
.
* @param value if {@code true}, continue after shutdown, else don't
* @see #getContinueExistingPeriodicTasksAfterShutdownPolicy
* @see #getContinueExistingPeriodicTasksAfterShutdownPolicy
*/
*/
public
void
setContinueExistingPeriodicTasksAfterShutdownPolicy
(
boolean
value
)
{
public
void
setContinueExistingPeriodicTasksAfterShutdownPolicy
(
boolean
value
)
{
...
@@ -686,7 +686,7 @@ public class ScheduledThreadPoolExecutor
...
@@ -686,7 +686,7 @@ public class ScheduledThreadPoolExecutor
* {@code false} when already shutdown.
* {@code false} when already shutdown.
* This value is by default {@code true}.
* This value is by default {@code true}.
*
*
* @param value if {@code true}, execute after shutdown, else don't
.
* @param value if {@code true}, execute after shutdown, else don't
* @see #getExecuteExistingDelayedTasksAfterShutdownPolicy
* @see #getExecuteExistingDelayedTasksAfterShutdownPolicy
*/
*/
public
void
setExecuteExistingDelayedTasksAfterShutdownPolicy
(
boolean
value
)
{
public
void
setExecuteExistingDelayedTasksAfterShutdownPolicy
(
boolean
value
)
{
...
@@ -1081,7 +1081,8 @@ public class ScheduledThreadPoolExecutor
...
@@ -1081,7 +1081,8 @@ public class ScheduledThreadPoolExecutor
long
delay
=
first
.
getDelay
(
NANOSECONDS
);
long
delay
=
first
.
getDelay
(
NANOSECONDS
);
if
(
delay
<=
0
)
if
(
delay
<=
0
)
return
finishPoll
(
first
);
return
finishPoll
(
first
);
else
if
(
leader
!=
null
)
first
=
null
;
// don't retain ref while waiting
if
(
leader
!=
null
)
available
.
await
();
available
.
await
();
else
{
else
{
Thread
thisThread
=
Thread
.
currentThread
();
Thread
thisThread
=
Thread
.
currentThread
();
...
@@ -1121,6 +1122,7 @@ public class ScheduledThreadPoolExecutor
...
@@ -1121,6 +1122,7 @@ public class ScheduledThreadPoolExecutor
return
finishPoll
(
first
);
return
finishPoll
(
first
);
if
(
nanos
<=
0
)
if
(
nanos
<=
0
)
return
null
;
return
null
;
first
=
null
;
// don't retain ref while waiting
if
(
nanos
<
delay
||
leader
!=
null
)
if
(
nanos
<
delay
||
leader
!=
null
)
nanos
=
available
.
awaitNanos
(
nanos
);
nanos
=
available
.
awaitNanos
(
nanos
);
else
{
else
{
...
...
src/share/classes/java/util/concurrent/ThreadPoolExecutor.java
浏览文件 @
6693c900
...
@@ -75,22 +75,23 @@ import java.util.*;
...
@@ -75,22 +75,23 @@ import java.util.*;
* corePoolSize (see {@link #getCorePoolSize}) and
* corePoolSize (see {@link #getCorePoolSize}) and
* maximumPoolSize (see {@link #getMaximumPoolSize}).
* maximumPoolSize (see {@link #getMaximumPoolSize}).
*
*
* When a new task is submitted in method {@link #execute}, and fewer
* When a new task is submitted in method {@link #execute(Runnable)},
* than corePoolSize threads are running, a new thread is created to
* and fewer than corePoolSize threads are running, a new thread is
* handle the request, even if other worker threads are idle. If
* created to handle the request, even if other worker threads are
* there are more than corePoolSize but less than maximumPoolSize
* idle. If there are more than corePoolSize but less than
* threads running, a new thread will be created only if the queue is
* maximumPoolSize threads running, a new thread will be created only
* full. By setting corePoolSize and maximumPoolSize the same, you
* if the queue is full. By setting corePoolSize and maximumPoolSize
* create a fixed-size thread pool. By setting maximumPoolSize to an
* the same, you create a fixed-size thread pool. By setting
* essentially unbounded value such as {@code Integer.MAX_VALUE}, you
* maximumPoolSize to an essentially unbounded value such as {@code
* allow the pool to accommodate an arbitrary number of concurrent
* Integer.MAX_VALUE}, you allow the pool to accommodate an arbitrary
* tasks. Most typically, core and maximum pool sizes are set only
* number of concurrent tasks. Most typically, core and maximum pool
* upon construction, but they may also be changed dynamically using
* sizes are set only upon construction, but they may also be changed
* {@link #setCorePoolSize} and {@link #setMaximumPoolSize}. </dd>
* dynamically using {@link #setCorePoolSize} and {@link
* #setMaximumPoolSize}. </dd>
*
*
* <dt>On-demand construction</dt>
* <dt>On-demand construction</dt>
*
*
* <dd>
By default, even core threads are initially created and
* <dd>By default, even core threads are initially created and
* started only when new tasks arrive, but this can be overridden
* started only when new tasks arrive, but this can be overridden
* dynamically using method {@link #prestartCoreThread} or {@link
* dynamically using method {@link #prestartCoreThread} or {@link
* #prestartAllCoreThreads}. You probably want to prestart threads if
* #prestartAllCoreThreads}. You probably want to prestart threads if
...
@@ -117,17 +118,17 @@ import java.util.*;
...
@@ -117,17 +118,17 @@ import java.util.*;
*
*
* <dd>If the pool currently has more than corePoolSize threads,
* <dd>If the pool currently has more than corePoolSize threads,
* excess threads will be terminated if they have been idle for more
* excess threads will be terminated if they have been idle for more
* than the keepAliveTime (see {@link #getKeepAliveTime
}). This
* than the keepAliveTime (see {@link #getKeepAliveTime
(TimeUnit)}).
*
provides a means of reducing resource consumption when the pool is
*
This provides a means of reducing resource consumption when the
*
not being actively used. If the pool becomes more active later, new
*
pool is not being actively used. If the pool becomes more active
*
threads will be constructed. This parameter can also be changed
*
later, new threads will be constructed. This parameter can also be
*
dynamically using method {@link #setKeepAliveTime}. Using a value
*
changed dynamically using method {@link #setKeepAliveTime(long,
*
of {@code Long.MAX_VALUE} {@link TimeUnit#NANOSECONDS} effectively
*
TimeUnit)}. Using a value of {@code Long.MAX_VALUE} {@link
*
disables idle threads from ever terminating prior to shut down. By
*
TimeUnit#NANOSECONDS} effectively disables idle threads from ever
*
default, the keep-alive policy applies only when there are more
*
terminating prior to shut down. By default, the keep-alive policy
*
than corePoolSizeThreads. But method {@link
*
applies only when there are more than corePoolSize threads. But
*
#allowCoreThreadTimeOut(boolean)} can be used to apply this
*
method {@link #allowCoreThreadTimeOut(boolean)} can be used to
* time-out policy to core threads as well, so long as the
*
apply this
time-out policy to core threads as well, so long as the
* keepAliveTime value is non-zero. </dd>
* keepAliveTime value is non-zero. </dd>
*
*
* <dt>Queuing</dt>
* <dt>Queuing</dt>
...
@@ -197,14 +198,14 @@ import java.util.*;
...
@@ -197,14 +198,14 @@ import java.util.*;
*
*
* <dt>Rejected tasks</dt>
* <dt>Rejected tasks</dt>
*
*
* <dd>
New tasks submitted in method {@link #execute
} will be
* <dd>
New tasks submitted in method {@link #execute(Runnable)
} will be
* <em>rejected</em> when the Executor has been shut down, and also
* <em>rejected</em> when the Executor has been shut down, and also
when
*
when the Executor uses finite bounds for both maximum threads and
*
the Executor uses finite bounds for both maximum threads and work queue
*
work queue capacity, and is saturated. In either case, the {@code
*
capacity, and is saturated. In either case, the {@code execute} method
*
execute} method
invokes the {@link
* invokes the {@link
* RejectedExecutionHandler#rejectedExecution
} method of its {@link
* RejectedExecutionHandler#rejectedExecution
(Runnable, ThreadPoolExecutor)}
*
RejectedExecutionHandler}. Four predefined handler policies are
*
method of its {@link RejectedExecutionHandler}. Four predefined handler
* provided:
* p
olicies are p
rovided:
*
*
* <ol>
* <ol>
*
*
...
@@ -234,30 +235,31 @@ import java.util.*;
...
@@ -234,30 +235,31 @@ import java.util.*;
*
*
* <dt>Hook methods</dt>
* <dt>Hook methods</dt>
*
*
* <dd>This class provides {@code protected} overridable {@link
* <dd>This class provides {@code protected} overridable
* #beforeExecute} and {@link #afterExecute} methods that are called
* {@link #beforeExecute(Thread, Runnable)} and
* {@link #afterExecute(Runnable, Throwable)} methods that are called
* before and after execution of each task. These can be used to
* before and after execution of each task. These can be used to
* manipulate the execution environment; for example, reinitializing
* manipulate the execution environment; for example, reinitializing
* ThreadLocals, gathering statistics, or adding log
* ThreadLocals, gathering statistics, or adding log
entries.
*
entries. Additionally, method {@link #terminated} can be overridden
*
Additionally, method {@link #terminated} can be overridden to perform
*
to perform any special processing that needs to be done once the
*
any special processing that needs to be done once the Executor has
*
Executor has
fully terminated.
* fully terminated.
*
*
* <p>If hook or callback methods throw exceptions, internal worker
* <p>If hook or callback methods throw exceptions, internal worker
* threads may in turn fail and abruptly terminate.</dd>
* threads may in turn fail and abruptly terminate.</dd>
*
*
* <dt>Queue maintenance</dt>
* <dt>Queue maintenance</dt>
*
*
* <dd>
Method {@link #getQueue} allows access to the work queue for
* <dd>
Method {@link #getQueue()} allows access to the work queue
*
purposes of monitoring and debugging. Use of this method for any
*
for purposes of monitoring and debugging. Use of this method for
* other purpose is strongly discouraged. Two supplied methods,
*
any
other purpose is strongly discouraged. Two supplied methods,
* {@link #remove
} and {@link #purge} are available to assist in
* {@link #remove
(Runnable)} and {@link #purge} are available to
*
storage reclamation when large numbers of queued tasks become
*
assist in storage reclamation when large numbers of queued tasks
* cancelled.</dd>
*
become
cancelled.</dd>
*
*
* <dt>Finalization</dt>
* <dt>Finalization</dt>
*
*
* <dd>
A pool that is no longer referenced in a program <em>AND</em>
* <dd>A pool that is no longer referenced in a program <em>AND</em>
* has no remaining threads will be {@code shutdown} automatically. If
* has no remaining threads will be {@code shutdown} automatically. If
* you would like to ensure that unreferenced pools are reclaimed even
* you would like to ensure that unreferenced pools are reclaimed even
* if users forget to call {@link #shutdown}, then you must arrange
* if users forget to call {@link #shutdown}, then you must arrange
...
@@ -267,7 +269,7 @@ import java.util.*;
...
@@ -267,7 +269,7 @@ import java.util.*;
*
*
* </dl>
* </dl>
*
*
* <p>
<b>Extension example</b>. Most extensions of this class
* <p><b>Extension example</b>. Most extensions of this class
* override one or more of the protected hook methods. For example,
* override one or more of the protected hook methods. For example,
* here is a subclass that adds a simple pause/resume feature:
* here is a subclass that adds a simple pause/resume feature:
*
*
...
@@ -336,7 +338,7 @@ public class ThreadPoolExecutor extends AbstractExecutorService {
...
@@ -336,7 +338,7 @@ public class ThreadPoolExecutor extends AbstractExecutorService {
* bookkeeping before terminating. The user-visible pool size is
* bookkeeping before terminating. The user-visible pool size is
* reported as the current size of the workers set.
* reported as the current size of the workers set.
*
*
* The runState provides the main lifecyle control, taking on values:
* The runState provides the main lifecy
c
le control, taking on values:
*
*
* RUNNING: Accept new tasks and process queued tasks
* RUNNING: Accept new tasks and process queued tasks
* SHUTDOWN: Don't accept new tasks, but process queued tasks
* SHUTDOWN: Don't accept new tasks, but process queued tasks
...
@@ -406,14 +408,14 @@ public class ThreadPoolExecutor extends AbstractExecutorService {
...
@@ -406,14 +408,14 @@ public class ThreadPoolExecutor extends AbstractExecutorService {
}
}
/**
/**
* Attempt to CAS-increment the workerCount field of ctl.
* Attempt
s
to CAS-increment the workerCount field of ctl.
*/
*/
private
boolean
compareAndIncrementWorkerCount
(
int
expect
)
{
private
boolean
compareAndIncrementWorkerCount
(
int
expect
)
{
return
ctl
.
compareAndSet
(
expect
,
expect
+
1
);
return
ctl
.
compareAndSet
(
expect
,
expect
+
1
);
}
}
/**
/**
* Attempt to CAS-decrement the workerCount field of ctl.
* Attempt
s
to CAS-decrement the workerCount field of ctl.
*/
*/
private
boolean
compareAndDecrementWorkerCount
(
int
expect
)
{
private
boolean
compareAndDecrementWorkerCount
(
int
expect
)
{
return
ctl
.
compareAndSet
(
expect
,
expect
-
1
);
return
ctl
.
compareAndSet
(
expect
,
expect
-
1
);
...
@@ -498,7 +500,7 @@ public class ThreadPoolExecutor extends AbstractExecutorService {
...
@@ -498,7 +500,7 @@ public class ThreadPoolExecutor extends AbstractExecutorService {
* We go further and preserve pool invariants even in the face of
* We go further and preserve pool invariants even in the face of
* errors such as OutOfMemoryError, that might be thrown while
* errors such as OutOfMemoryError, that might be thrown while
* trying to create threads. Such errors are rather common due to
* trying to create threads. Such errors are rather common due to
* the need to allocate a native stack in Thread
#
start, and users
* the need to allocate a native stack in Thread
.
start, and users
* will want to perform clean pool shutdown to clean up. There
* will want to perform clean pool shutdown to clean up. There
* will likely be enough memory available for the cleanup code to
* will likely be enough memory available for the cleanup code to
* complete without encountering yet another OutOfMemoryError.
* complete without encountering yet another OutOfMemoryError.
...
@@ -848,7 +850,7 @@ public class ThreadPoolExecutor extends AbstractExecutorService {
...
@@ -848,7 +850,7 @@ public class ThreadPoolExecutor extends AbstractExecutorService {
*/
*/
private
List
<
Runnable
>
drainQueue
()
{
private
List
<
Runnable
>
drainQueue
()
{
BlockingQueue
<
Runnable
>
q
=
workQueue
;
BlockingQueue
<
Runnable
>
q
=
workQueue
;
List
<
Runnable
>
taskList
=
new
ArrayList
<
Runnable
>();
Array
List
<
Runnable
>
taskList
=
new
ArrayList
<
Runnable
>();
q
.
drainTo
(
taskList
);
q
.
drainTo
(
taskList
);
if
(!
q
.
isEmpty
())
{
if
(!
q
.
isEmpty
())
{
for
(
Runnable
r
:
q
.
toArray
(
new
Runnable
[
0
]))
{
for
(
Runnable
r
:
q
.
toArray
(
new
Runnable
[
0
]))
{
...
@@ -873,7 +875,7 @@ public class ThreadPoolExecutor extends AbstractExecutorService {
...
@@ -873,7 +875,7 @@ public class ThreadPoolExecutor extends AbstractExecutorService {
* factory fails to create a thread when asked. If the thread
* factory fails to create a thread when asked. If the thread
* creation fails, either due to the thread factory returning
* creation fails, either due to the thread factory returning
* null, or due to an exception (typically OutOfMemoryError in
* null, or due to an exception (typically OutOfMemoryError in
* Thread
#start
), we roll back cleanly.
* Thread
.start()
), we roll back cleanly.
*
*
* @param firstTask the task the new thread should run first (or
* @param firstTask the task the new thread should run first (or
* null if none). Workers are created with an initial first task
* null if none). Workers are created with an initial first task
...
@@ -920,17 +922,16 @@ public class ThreadPoolExecutor extends AbstractExecutorService {
...
@@ -920,17 +922,16 @@ public class ThreadPoolExecutor extends AbstractExecutorService {
boolean
workerAdded
=
false
;
boolean
workerAdded
=
false
;
Worker
w
=
null
;
Worker
w
=
null
;
try
{
try
{
final
ReentrantLock
mainLock
=
this
.
mainLock
;
w
=
new
Worker
(
firstTask
);
w
=
new
Worker
(
firstTask
);
final
Thread
t
=
w
.
thread
;
final
Thread
t
=
w
.
thread
;
if
(
t
!=
null
)
{
if
(
t
!=
null
)
{
final
ReentrantLock
mainLock
=
this
.
mainLock
;
mainLock
.
lock
();
mainLock
.
lock
();
try
{
try
{
// Recheck while holding lock.
// Recheck while holding lock.
// Back out on ThreadFactory failure or if
// Back out on ThreadFactory failure or if
// shut down before lock acquired.
// shut down before lock acquired.
int
c
=
ctl
.
get
();
int
rs
=
runStateOf
(
ctl
.
get
());
int
rs
=
runStateOf
(
c
);
if
(
rs
<
SHUTDOWN
||
if
(
rs
<
SHUTDOWN
||
(
rs
==
SHUTDOWN
&&
firstTask
==
null
))
{
(
rs
==
SHUTDOWN
&&
firstTask
==
null
))
{
...
@@ -1029,7 +1030,8 @@ public class ThreadPoolExecutor extends AbstractExecutorService {
...
@@ -1029,7 +1030,8 @@ public class ThreadPoolExecutor extends AbstractExecutorService {
* 4. This worker timed out waiting for a task, and timed-out
* 4. This worker timed out waiting for a task, and timed-out
* workers are subject to termination (that is,
* workers are subject to termination (that is,
* {@code allowCoreThreadTimeOut || workerCount > corePoolSize})
* {@code allowCoreThreadTimeOut || workerCount > corePoolSize})
* both before and after the timed wait.
* both before and after the timed wait, and if the queue is
* non-empty, this worker is not the last thread in the pool.
*
*
* @return task, or null if the worker must exit, in which case
* @return task, or null if the worker must exit, in which case
* workerCount is decremented
* workerCount is decremented
...
@@ -1037,7 +1039,6 @@ public class ThreadPoolExecutor extends AbstractExecutorService {
...
@@ -1037,7 +1039,6 @@ public class ThreadPoolExecutor extends AbstractExecutorService {
private
Runnable
getTask
()
{
private
Runnable
getTask
()
{
boolean
timedOut
=
false
;
// Did the last poll() time out?
boolean
timedOut
=
false
;
// Did the last poll() time out?
retry:
for
(;;)
{
for
(;;)
{
int
c
=
ctl
.
get
();
int
c
=
ctl
.
get
();
int
rs
=
runStateOf
(
c
);
int
rs
=
runStateOf
(
c
);
...
@@ -1048,20 +1049,16 @@ public class ThreadPoolExecutor extends AbstractExecutorService {
...
@@ -1048,20 +1049,16 @@ public class ThreadPoolExecutor extends AbstractExecutorService {
return
null
;
return
null
;
}
}
boolean
timed
;
// Are workers subject to culling?
int
wc
=
workerCountOf
(
c
);
for
(;;)
{
// Are workers subject to culling?
int
wc
=
workerCountOf
(
c
);
boolean
timed
=
allowCoreThreadTimeOut
||
wc
>
corePoolSize
;
timed
=
allowCoreThreadTimeOut
||
wc
>
corePoolSize
;
if
(
wc
<=
maximumPoolSize
&&
!
(
timedOut
&&
timed
))
if
((
wc
>
maximumPoolSize
||
(
timed
&&
timedOut
))
break
;
&&
(
wc
>
1
||
workQueue
.
isEmpty
()))
{
if
(
compareAndDecrementWorkerCount
(
c
))
if
(
compareAndDecrementWorkerCount
(
c
))
return
null
;
return
null
;
c
=
ctl
.
get
();
// Re-read ctl
continue
;
if
(
runStateOf
(
c
)
!=
rs
)
continue
retry
;
// else CAS failed due to workerCount change; retry inner loop
}
}
try
{
try
{
...
@@ -1090,9 +1087,9 @@ public class ThreadPoolExecutor extends AbstractExecutorService {
...
@@ -1090,9 +1087,9 @@ public class ThreadPoolExecutor extends AbstractExecutorService {
* usually leads processWorkerExit to replace this thread.
* usually leads processWorkerExit to replace this thread.
*
*
* 2. Before running any task, the lock is acquired to prevent
* 2. Before running any task, the lock is acquired to prevent
* other pool interrupts while the task is executing, and
* other pool interrupts while the task is executing, and
then we
*
clearInterruptsForTaskRun called to ensure that unless pool is
*
ensure that unless pool is stopping, this thread does not have
*
stopping, this thread does not have
its interrupt set.
* its interrupt set.
*
*
* 3. Each task run is preceded by a call to beforeExecute, which
* 3. Each task run is preceded by a call to beforeExecute, which
* might throw an exception, in which case we cause thread to die
* might throw an exception, in which case we cause thread to die
...
@@ -1100,12 +1097,12 @@ public class ThreadPoolExecutor extends AbstractExecutorService {
...
@@ -1100,12 +1097,12 @@ public class ThreadPoolExecutor extends AbstractExecutorService {
* the task.
* the task.
*
*
* 4. Assuming beforeExecute completes normally, we run the task,
* 4. Assuming beforeExecute completes normally, we run the task,
* gathering any of its thrown exceptions to send to
* gathering any of its thrown exceptions to send to
afterExecute.
*
afterExecute. We separately handle RuntimeException, Error
*
We separately handle RuntimeException, Error (both of which the
*
(both of which the specs guarantee that we trap) and arbitrary
*
specs guarantee that we trap) and arbitrary Throwables.
*
Throwables. Because we cannot rethrow Throwables within
*
Because we cannot rethrow Throwables within Runnable.run, we
*
Runnable.run, we wrap them within Errors on the way out (to the
*
wrap them within Errors on the way out (to the thread's
*
thread's
UncaughtExceptionHandler). Any thrown exception also
* UncaughtExceptionHandler). Any thrown exception also
* conservatively causes thread to die.
* conservatively causes thread to die.
*
*
* 5. After task.run completes, we call afterExecute, which may
* 5. After task.run completes, we call afterExecute, which may
...
@@ -1443,7 +1440,7 @@ public class ThreadPoolExecutor extends AbstractExecutorService {
...
@@ -1443,7 +1440,7 @@ public class ThreadPoolExecutor extends AbstractExecutorService {
* ignored or suppressed interruption, causing this executor not
* ignored or suppressed interruption, causing this executor not
* to properly terminate.
* to properly terminate.
*
*
* @return
true
if terminating but not yet terminated
* @return
{@code true}
if terminating but not yet terminated
*/
*/
public
boolean
isTerminating
()
{
public
boolean
isTerminating
()
{
int
c
=
ctl
.
get
();
int
c
=
ctl
.
get
();
...
@@ -1497,7 +1494,7 @@ public class ThreadPoolExecutor extends AbstractExecutorService {
...
@@ -1497,7 +1494,7 @@ public class ThreadPoolExecutor extends AbstractExecutorService {
* Returns the thread factory used to create new threads.
* Returns the thread factory used to create new threads.
*
*
* @return the current thread factory
* @return the current thread factory
* @see #setThreadFactory
* @see #setThreadFactory
(ThreadFactory)
*/
*/
public
ThreadFactory
getThreadFactory
()
{
public
ThreadFactory
getThreadFactory
()
{
return
threadFactory
;
return
threadFactory
;
...
@@ -1520,7 +1517,7 @@ public class ThreadPoolExecutor extends AbstractExecutorService {
...
@@ -1520,7 +1517,7 @@ public class ThreadPoolExecutor extends AbstractExecutorService {
* Returns the current handler for unexecutable tasks.
* Returns the current handler for unexecutable tasks.
*
*
* @return the current handler
* @return the current handler
* @see #setRejectedExecutionHandler
* @see #setRejectedExecutionHandler
(RejectedExecutionHandler)
*/
*/
public
RejectedExecutionHandler
getRejectedExecutionHandler
()
{
public
RejectedExecutionHandler
getRejectedExecutionHandler
()
{
return
handler
;
return
handler
;
...
@@ -1692,7 +1689,7 @@ public class ThreadPoolExecutor extends AbstractExecutorService {
...
@@ -1692,7 +1689,7 @@ public class ThreadPoolExecutor extends AbstractExecutorService {
* @param unit the time unit of the {@code time} argument
* @param unit the time unit of the {@code time} argument
* @throws IllegalArgumentException if {@code time} less than zero or
* @throws IllegalArgumentException if {@code time} less than zero or
* if {@code time} is zero and {@code allowsCoreThreadTimeOut}
* if {@code time} is zero and {@code allowsCoreThreadTimeOut}
* @see #getKeepAliveTime
* @see #getKeepAliveTime
(TimeUnit)
*/
*/
public
void
setKeepAliveTime
(
long
time
,
TimeUnit
unit
)
{
public
void
setKeepAliveTime
(
long
time
,
TimeUnit
unit
)
{
if
(
time
<
0
)
if
(
time
<
0
)
...
@@ -1713,7 +1710,7 @@ public class ThreadPoolExecutor extends AbstractExecutorService {
...
@@ -1713,7 +1710,7 @@ public class ThreadPoolExecutor extends AbstractExecutorService {
*
*
* @param unit the desired time unit of the result
* @param unit the desired time unit of the result
* @return the time limit
* @return the time limit
* @see #setKeepAliveTime
* @see #setKeepAliveTime
(long, TimeUnit)
*/
*/
public
long
getKeepAliveTime
(
TimeUnit
unit
)
{
public
long
getKeepAliveTime
(
TimeUnit
unit
)
{
return
unit
.
convert
(
keepAliveTime
,
TimeUnit
.
NANOSECONDS
);
return
unit
.
convert
(
keepAliveTime
,
TimeUnit
.
NANOSECONDS
);
...
@@ -1738,7 +1735,7 @@ public class ThreadPoolExecutor extends AbstractExecutorService {
...
@@ -1738,7 +1735,7 @@ public class ThreadPoolExecutor extends AbstractExecutorService {
* present, thus causing it not to be run if it has not already
* present, thus causing it not to be run if it has not already
* started.
* started.
*
*
* <p>
This method may be useful as one part of a cancellation
* <p>This method may be useful as one part of a cancellation
* scheme. It may fail to remove tasks that have been converted
* scheme. It may fail to remove tasks that have been converted
* into other forms before being placed on the internal queue. For
* into other forms before being placed on the internal queue. For
* example, a task entered using {@code submit} might be
* example, a task entered using {@code submit} might be
...
@@ -1747,7 +1744,7 @@ public class ThreadPoolExecutor extends AbstractExecutorService {
...
@@ -1747,7 +1744,7 @@ public class ThreadPoolExecutor extends AbstractExecutorService {
* remove those Futures that have been cancelled.
* remove those Futures that have been cancelled.
*
*
* @param task the task to remove
* @param task the task to remove
* @return
true
if the task was removed
* @return
{@code true}
if the task was removed
*/
*/
public
boolean
remove
(
Runnable
task
)
{
public
boolean
remove
(
Runnable
task
)
{
boolean
removed
=
workQueue
.
remove
(
task
);
boolean
removed
=
workQueue
.
remove
(
task
);
...
@@ -2042,7 +2039,7 @@ public class ThreadPoolExecutor extends AbstractExecutorService {
...
@@ -2042,7 +2039,7 @@ public class ThreadPoolExecutor extends AbstractExecutorService {
*
*
* @param r the runnable task requested to be executed
* @param r the runnable task requested to be executed
* @param e the executor attempting to execute this task
* @param e the executor attempting to execute this task
* @throws RejectedExecutionException always
.
* @throws RejectedExecutionException always
*/
*/
public
void
rejectedExecution
(
Runnable
r
,
ThreadPoolExecutor
e
)
{
public
void
rejectedExecution
(
Runnable
r
,
ThreadPoolExecutor
e
)
{
throw
new
RejectedExecutionException
(
"Task "
+
r
.
toString
()
+
throw
new
RejectedExecutionException
(
"Task "
+
r
.
toString
()
+
...
@@ -2099,4 +2096,3 @@ public class ThreadPoolExecutor extends AbstractExecutorService {
...
@@ -2099,4 +2096,3 @@ public class ThreadPoolExecutor extends AbstractExecutorService {
}
}
}
}
}
}
src/share/classes/java/util/regex/MatchResult.java
浏览文件 @
6693c900
/*
/*
* Copyright (c) 2003, 20
04
, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2003, 20
13
, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
*
* This code is free software; you can redistribute it and/or modify it
* This code is free software; you can redistribute it and/or modify it
...
@@ -77,7 +77,7 @@ public interface MatchResult {
...
@@ -77,7 +77,7 @@ public interface MatchResult {
public
int
start
(
int
group
);
public
int
start
(
int
group
);
/**
/**
* Returns the offset after the last character matched.
</p>
* Returns the offset after the last character matched.
*
*
* @return The offset after the last character matched
* @return The offset after the last character matched
*
*
...
...
src/share/classes/java/util/regex/Matcher.java
浏览文件 @
6693c900
/*
/*
* Copyright (c) 1999, 201
2
, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1999, 201
3
, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
*
* This code is free software; you can redistribute it and/or modify it
* This code is free software; you can redistribute it and/or modify it
...
@@ -28,8 +28,8 @@ package java.util.regex;
...
@@ -28,8 +28,8 @@ package java.util.regex;
import
java.util.Objects
;
import
java.util.Objects
;
/**
/**
* An engine that performs match operations on a {@link java.lang.CharSequence
* An engine that performs match operations on a {@link
plain
java.lang.CharSequence
*
</code>character sequence<code>
} by interpreting a {@link Pattern}.
*
character sequence
} by interpreting a {@link Pattern}.
*
*
* <p> A matcher is created from a pattern by invoking the pattern's {@link
* <p> A matcher is created from a pattern by invoking the pattern's {@link
* Pattern#matcher matcher} method. Once created, a matcher can be used to
* Pattern#matcher matcher} method. Once created, a matcher can be used to
...
@@ -330,7 +330,7 @@ public final class Matcher implements MatchResult {
...
@@ -330,7 +330,7 @@ public final class Matcher implements MatchResult {
}
}
/**
/**
* Returns the start index of the previous match.
</p>
* Returns the start index of the previous match.
*
*
* @return The index of the first character matched
* @return The index of the first character matched
*
*
...
@@ -402,7 +402,7 @@ public final class Matcher implements MatchResult {
...
@@ -402,7 +402,7 @@ public final class Matcher implements MatchResult {
}
}
/**
/**
* Returns the offset after the last character matched.
</p>
* Returns the offset after the last character matched.
*
*
* @return The offset after the last character matched
* @return The offset after the last character matched
*
*
...
@@ -647,6 +647,7 @@ public final class Matcher implements MatchResult {
...
@@ -647,6 +647,7 @@ public final class Matcher implements MatchResult {
* invocations of the {@link #find()} method will start at the first
* invocations of the {@link #find()} method will start at the first
* character not matched by this match. </p>
* character not matched by this match. </p>
*
*
* @param start the index to start searching for a match
* @throws IndexOutOfBoundsException
* @throws IndexOutOfBoundsException
* If start is less than zero or if start is greater than the
* If start is less than zero or if start is greater than the
* length of the input sequence.
* length of the input sequence.
...
@@ -736,8 +737,8 @@ public final class Matcher implements MatchResult {
...
@@ -736,8 +737,8 @@ public final class Matcher implements MatchResult {
* captured during the previous match: Each occurrence of
* captured during the previous match: Each occurrence of
* <tt>${</tt><i>name</i><tt>}</tt> or <tt>$</tt><i>g</i>
* <tt>${</tt><i>name</i><tt>}</tt> or <tt>$</tt><i>g</i>
* will be replaced by the result of evaluating the corresponding
* will be replaced by the result of evaluating the corresponding
* {@link #group(String) group(name)} or {@link #group(int) group(g)
</tt>
}
* {@link #group(String) group(name)} or {@link #group(int) group(g)}
* respectively. For <tt>$</tt><i>g</i>
<tt></tt>
,
* respectively. For <tt>$</tt><i>g</i>,
* the first number after the <tt>$</tt> is always treated as part of
* the first number after the <tt>$</tt> is always treated as part of
* the group reference. Subsequent numbers are incorporated into g if
* the group reference. Subsequent numbers are incorporated into g if
* they would form a legal group reference. Only the numerals '0'
* they would form a legal group reference. Only the numerals '0'
...
...
src/share/classes/java/util/regex/Pattern.java
浏览文件 @
6693c900
...
@@ -45,8 +45,8 @@ import java.util.stream.StreamSupport;
...
@@ -45,8 +45,8 @@ import java.util.stream.StreamSupport;
*
*
* <p> A regular expression, specified as a string, must first be compiled into
* <p> A regular expression, specified as a string, must first be compiled into
* an instance of this class. The resulting pattern can then be used to create
* an instance of this class. The resulting pattern can then be used to create
* a {@link Matcher} object that can match arbitrary {@link
* a {@link Matcher} object that can match arbitrary {@link
plain
* java.lang.CharSequence
</code>character sequences<code>
} against the regular
* java.lang.CharSequence
character sequences
} against the regular
* expression. All of the state involved in performing a match resides in the
* expression. All of the state involved in performing a match resides in the
* matcher, so many matchers can share the same pattern.
* matcher, so many matchers can share the same pattern.
*
*
...
@@ -73,15 +73,14 @@ import java.util.stream.StreamSupport;
...
@@ -73,15 +73,14 @@ import java.util.stream.StreamSupport;
* such use.
* such use.
*
*
*
*
* <a name="sum">
* <h3><a name="sum">Summary of regular-expression constructs</a></h3>
* <h4> Summary of regular-expression constructs </h4>
*
*
* <table border="0" cellpadding="1" cellspacing="0"
* <table border="0" cellpadding="1" cellspacing="0"
* summary="Regular expression constructs, and what they match">
* summary="Regular expression constructs, and what they match">
*
*
* <tr align="left">
* <tr align="left">
* <th
bgcolor="#CCCCFF"
align="left" id="construct">Construct</th>
* <th align="left" id="construct">Construct</th>
* <th
bgcolor="#CCCCFF"
align="left" id="matches">Matches</th>
* <th align="left" id="matches">Matches</th>
* </tr>
* </tr>
*
*
* <tr><th> </th></tr>
* <tr><th> </th></tr>
...
@@ -128,24 +127,24 @@ import java.util.stream.StreamSupport;
...
@@ -128,24 +127,24 @@ import java.util.stream.StreamSupport;
* <tr><th> </th></tr>
* <tr><th> </th></tr>
* <tr align="left"><th colspan="2" id="classes">Character classes</th></tr>
* <tr align="left"><th colspan="2" id="classes">Character classes</th></tr>
*
*
* <tr><td valign="top" headers="construct classes">
<tt>[abc]</tt>
</td>
* <tr><td valign="top" headers="construct classes">
{@code [abc]}
</td>
* <td headers="matches">
<tt>a</tt>, <tt>b</tt>, or <tt>c</tt>
(simple class)</td></tr>
* <td headers="matches">
{@code a}, {@code b}, or {@code c}
(simple class)</td></tr>
* <tr><td valign="top" headers="construct classes">
<tt>[^abc]</tt>
</td>
* <tr><td valign="top" headers="construct classes">
{@code [^abc]}
</td>
* <td headers="matches">Any character except
<tt>a</tt>, <tt>b</tt>, or <tt>c</tt>
(negation)</td></tr>
* <td headers="matches">Any character except
{@code a}, {@code b}, or {@code c}
(negation)</td></tr>
* <tr><td valign="top" headers="construct classes">
<tt>[a-zA-Z]</tt>
</td>
* <tr><td valign="top" headers="construct classes">
{@code [a-zA-Z]}
</td>
* <td headers="matches">
<tt>a</tt> through <tt>z</tt>
* <td headers="matches">
{@code a} through {@code z}
* or
<tt>A</tt> through <tt>Z</tt>
, inclusive (range)</td></tr>
* or
{@code A} through {@code Z}
, inclusive (range)</td></tr>
* <tr><td valign="top" headers="construct classes">
<tt>[a-d[m-p]]</tt>
</td>
* <tr><td valign="top" headers="construct classes">
{@code [a-d[m-p]]}
</td>
* <td headers="matches">
<tt>a</tt> through <tt>d</tt>
,
* <td headers="matches">
{@code a} through {@code d}
,
* or
<tt>m</tt> through <tt>p</tt>: <tt>[a-dm-p]</tt>
(union)</td></tr>
* or
{@code m} through {@code p}: {@code [a-dm-p]}
(union)</td></tr>
* <tr><td valign="top" headers="construct classes">
<tt>[a-z&&[def]]</tt>
</td>
* <tr><td valign="top" headers="construct classes">
{@code [a-z&&[def]]}
</td>
* <td headers="matches">
<tt>d</tt>, <tt>e</tt>, or <tt>f</tt>
(intersection)</tr>
* <td headers="matches">
{@code d}, {@code e}, or {@code f}
(intersection)</tr>
* <tr><td valign="top" headers="construct classes">
<tt>[a-z&&[^bc]]</tt>
</td>
* <tr><td valign="top" headers="construct classes">
{@code [a-z&&[^bc]]}
</td>
* <td headers="matches">
<tt>a</tt> through <tt>z</tt>
,
* <td headers="matches">
{@code a} through {@code z}
,
* except for
<tt>b</tt> and <tt>c</tt>: <tt>[ad-z]</tt>
(subtraction)</td></tr>
* except for
{@code b} and {@code c}: {@code [ad-z]}
(subtraction)</td></tr>
* <tr><td valign="top" headers="construct classes">
<tt>[a-z&&[^m-p]]</tt>
</td>
* <tr><td valign="top" headers="construct classes">
{@code [a-z&&[^m-p]]}
</td>
* <td headers="matches">
<tt>a</tt> through <tt>z</tt>
,
* <td headers="matches">
{@code a} through {@code z}
,
* and not
<tt>m</tt> through <tt>p</tt>: <tt>[a-lq-z]</tt>
(subtraction)</td></tr>
* and not
{@code m} through {@code p}: {@code [a-lq-z]}
(subtraction)</td></tr>
* <tr><th> </th></tr>
* <tr><th> </th></tr>
*
*
* <tr align="left"><th colspan="2" id="predef">Predefined character classes</th></tr>
* <tr align="left"><th colspan="2" id="predef">Predefined character classes</th></tr>
...
@@ -175,36 +174,36 @@ import java.util.stream.StreamSupport;
...
@@ -175,36 +174,36 @@ import java.util.stream.StreamSupport;
* <tr><td valign="top" headers="construct predef"><tt>\W</tt></td>
* <tr><td valign="top" headers="construct predef"><tt>\W</tt></td>
* <td headers="matches">A non-word character: <tt>[^\w]</tt></td></tr>
* <td headers="matches">A non-word character: <tt>[^\w]</tt></td></tr>
* <tr><th> </th></tr>
* <tr><th> </th></tr>
* <tr align="left"><th colspan="2" id="posix">
POSIX character classes</b> (US-ASCII only)<
b></th></tr>
* <tr align="left"><th colspan="2" id="posix">
<b>POSIX character classes (US-ASCII only)</
b></th></tr>
*
*
* <tr><td valign="top" headers="construct posix">
<tt>\p{Lower}</tt>
</td>
* <tr><td valign="top" headers="construct posix">
{@code \p{Lower}}
</td>
* <td headers="matches">A lower-case alphabetic character:
<tt>[a-z]</tt>
</td></tr>
* <td headers="matches">A lower-case alphabetic character:
{@code [a-z]}
</td></tr>
* <tr><td valign="top" headers="construct posix">
<tt>\p{Upper}</tt>
</td>
* <tr><td valign="top" headers="construct posix">
{@code \p{Upper}}
</td>
* <td headers="matches">An upper-case alphabetic character:
<tt>[A-Z]</tt>
</td></tr>
* <td headers="matches">An upper-case alphabetic character:
{@code [A-Z]}
</td></tr>
* <tr><td valign="top" headers="construct posix">
<tt>\p{ASCII}</tt>
</td>
* <tr><td valign="top" headers="construct posix">
{@code \p{ASCII}}
</td>
* <td headers="matches">All ASCII:
<tt>[\x00-\x7F]</tt>
</td></tr>
* <td headers="matches">All ASCII:
{@code [\x00-\x7F]}
</td></tr>
* <tr><td valign="top" headers="construct posix">
<tt>\p{Alpha}</tt>
</td>
* <tr><td valign="top" headers="construct posix">
{@code \p{Alpha}}
</td>
* <td headers="matches">An alphabetic character:
<tt>[\p{Lower}\p{Upper}]</tt>
</td></tr>
* <td headers="matches">An alphabetic character:
{@code [\p{Lower}\p{Upper}]}
</td></tr>
* <tr><td valign="top" headers="construct posix">
<tt>\p{Digit}</tt>
</td>
* <tr><td valign="top" headers="construct posix">
{@code \p{Digit}}
</td>
* <td headers="matches">A decimal digit:
<tt>[0-9]</tt>
</td></tr>
* <td headers="matches">A decimal digit:
{@code [0-9]}
</td></tr>
* <tr><td valign="top" headers="construct posix">
<tt>\p{Alnum}</tt>
</td>
* <tr><td valign="top" headers="construct posix">
{@code \p{Alnum}}
</td>
* <td headers="matches">An alphanumeric character:
<tt>[\p{Alpha}\p{Digit}]</tt>
</td></tr>
* <td headers="matches">An alphanumeric character:
{@code [\p{Alpha}\p{Digit}]}
</td></tr>
* <tr><td valign="top" headers="construct posix">
<tt>\p{Punct}</tt>
</td>
* <tr><td valign="top" headers="construct posix">
{@code \p{Punct}}
</td>
* <td headers="matches">Punctuation: One of
<tt>!"#$%&'()*+,-./:;<=>?@[\]^_`{|}~</tt>
</td></tr>
* <td headers="matches">Punctuation: One of
{@code !"#$%&'()*+,-./:;<=>?@[\]^_`{|}~}
</td></tr>
* <!--
<tt>[\!"#\$%&'\(\)\*\+,\-\./:;\<=\>\?@\[\\\]\^_`\{\|\}~]</tt>
* <!--
{@code [\!"#\$%&'\(\)\*\+,\-\./:;\<=\>\?@\[\\\]\^_`\{\|\}~]}
*
<tt>[\X21-\X2F\X31-\X40\X5B-\X60\X7B-\X7E]</tt>
-->
*
{@code [\X21-\X2F\X31-\X40\X5B-\X60\X7B-\X7E]}
-->
* <tr><td valign="top" headers="construct posix">
<tt>\p{Graph}</tt>
</td>
* <tr><td valign="top" headers="construct posix">
{@code \p{Graph}}
</td>
* <td headers="matches">A visible character:
<tt>[\p{Alnum}\p{Punct}]</tt>
</td></tr>
* <td headers="matches">A visible character:
{@code [\p{Alnum}\p{Punct}]}
</td></tr>
* <tr><td valign="top" headers="construct posix">
<tt>\p{Print}</tt>
</td>
* <tr><td valign="top" headers="construct posix">
{@code \p{Print}}
</td>
* <td headers="matches">A printable character:
<tt>[\p{Graph}\x20]</tt>
</td></tr>
* <td headers="matches">A printable character:
{@code [\p{Graph}\x20]}
</td></tr>
* <tr><td valign="top" headers="construct posix">
<tt>\p{Blank}</tt>
</td>
* <tr><td valign="top" headers="construct posix">
{@code \p{Blank}}
</td>
* <td headers="matches">A space or a tab:
<tt>[ \t]</tt>
</td></tr>
* <td headers="matches">A space or a tab:
{@code [ \t]}
</td></tr>
* <tr><td valign="top" headers="construct posix">
<tt>\p{Cntrl}</tt>
</td>
* <tr><td valign="top" headers="construct posix">
{@code \p{Cntrl}}
</td>
* <td headers="matches">A control character:
<tt>[\x00-\x1F\x7F]</tt>
</td></tr>
* <td headers="matches">A control character:
{@code [\x00-\x1F\x7F]}
</td></tr>
* <tr><td valign="top" headers="construct posix">
<tt>\p{XDigit}</tt>
</td>
* <tr><td valign="top" headers="construct posix">
{@code \p{XDigit}}
</td>
* <td headers="matches">A hexadecimal digit:
<tt>[0-9a-fA-F]</tt>
</td></tr>
* <td headers="matches">A hexadecimal digit:
{@code [0-9a-fA-F]}
</td></tr>
* <tr><td valign="top" headers="construct posix">
<tt>\p{Space}</tt>
</td>
* <tr><td valign="top" headers="construct posix">
{@code \p{Space}}
</td>
* <td headers="matches">A whitespace character:
<tt>[ \t\n\x0B\f\r]</tt>
</td></tr>
* <td headers="matches">A whitespace character:
{@code [ \t\n\x0B\f\r]}
</td></tr>
*
*
* <tr><th> </th></tr>
* <tr><th> </th></tr>
* <tr align="left"><th colspan="2">java.lang.Character classes (simple <a href="#jcc">java character type</a>)</th></tr>
* <tr align="left"><th colspan="2">java.lang.Character classes (simple <a href="#jcc">java character type</a>)</th></tr>
...
@@ -220,19 +219,19 @@ import java.util.stream.StreamSupport;
...
@@ -220,19 +219,19 @@ import java.util.stream.StreamSupport;
*
*
* <tr><th> </th></tr>
* <tr><th> </th></tr>
* <tr align="left"><th colspan="2" id="unicode">Classes for Unicode scripts, blocks, categories and binary properties</th></tr>
* <tr align="left"><th colspan="2" id="unicode">Classes for Unicode scripts, blocks, categories and binary properties</th></tr>
* * <tr><td valign="top" headers="construct unicode">
<tt>\p{IsLatin}</tt>
</td>
* * <tr><td valign="top" headers="construct unicode">
{@code \p{IsLatin}}
</td>
* <td headers="matches">A Latin script character (<a href="#usc">script</a>)</td></tr>
* <td headers="matches">A Latin script character (<a href="#usc">script</a>)</td></tr>
* <tr><td valign="top" headers="construct unicode">
<tt>\p{InGreek}</tt>
</td>
* <tr><td valign="top" headers="construct unicode">
{@code \p{InGreek}}
</td>
* <td headers="matches">A character in the Greek block (<a href="#ubc">block</a>)</td></tr>
* <td headers="matches">A character in the Greek block (<a href="#ubc">block</a>)</td></tr>
* <tr><td valign="top" headers="construct unicode">
<tt>\p{Lu}</tt>
</td>
* <tr><td valign="top" headers="construct unicode">
{@code \p{Lu}}
</td>
* <td headers="matches">An uppercase letter (<a href="#ucc">category</a>)</td></tr>
* <td headers="matches">An uppercase letter (<a href="#ucc">category</a>)</td></tr>
* <tr><td valign="top" headers="construct unicode">
<tt>\p{IsAlphabetic}</tt>
</td>
* <tr><td valign="top" headers="construct unicode">
{@code \p{IsAlphabetic}}
</td>
* <td headers="matches">An alphabetic character (<a href="#ubpc">binary property</a>)</td></tr>
* <td headers="matches">An alphabetic character (<a href="#ubpc">binary property</a>)</td></tr>
* <tr><td valign="top" headers="construct unicode">
<tt>\p{Sc}</tt>
</td>
* <tr><td valign="top" headers="construct unicode">
{@code \p{Sc}}
</td>
* <td headers="matches">A currency symbol</td></tr>
* <td headers="matches">A currency symbol</td></tr>
* <tr><td valign="top" headers="construct unicode">
<tt>\P{InGreek}</tt>
</td>
* <tr><td valign="top" headers="construct unicode">
{@code \P{InGreek}}
</td>
* <td headers="matches">Any character except one in the Greek block (negation)</td></tr>
* <td headers="matches">Any character except one in the Greek block (negation)</td></tr>
* <tr><td valign="top" headers="construct unicode">
<tt>[\p{L}&&[^\p{Lu}]] </tt>
</td>
* <tr><td valign="top" headers="construct unicode">
{@code [\p{L}&&[^\p{Lu}]]}
</td>
* <td headers="matches">Any letter except an uppercase letter (subtraction)</td></tr>
* <td headers="matches">Any letter except an uppercase letter (subtraction)</td></tr>
*
*
* <tr><th> </th></tr>
* <tr><th> </th></tr>
...
@@ -376,8 +375,7 @@ import java.util.stream.StreamSupport;
...
@@ -376,8 +375,7 @@ import java.util.stream.StreamSupport;
* <hr>
* <hr>
*
*
*
*
* <a name="bs">
* <h3><a name="bs">Backslashes, escapes, and quoting</a></h3>
* <h4> Backslashes, escapes, and quoting </h4>
*
*
* <p> The backslash character (<tt>'\'</tt>) serves to introduce escaped
* <p> The backslash character (<tt>'\'</tt>) serves to introduce escaped
* constructs, as defined in the table above, as well as to quote characters
* constructs, as defined in the table above, as well as to quote characters
...
@@ -405,8 +403,7 @@ import java.util.stream.StreamSupport;
...
@@ -405,8 +403,7 @@ import java.util.stream.StreamSupport;
* <tt>(hello)</tt> the string literal <tt>"\\(hello\\)"</tt>
* <tt>(hello)</tt> the string literal <tt>"\\(hello\\)"</tt>
* must be used.
* must be used.
*
*
* <a name="cc">
* <h3><a name="cc">Character Classes</a></h3>
* <h4> Character Classes </h4>
*
*
* <p> Character classes may appear within other character classes, and
* <p> Character classes may appear within other character classes, and
* may be composed by the union operator (implicit) and the intersection
* may be composed by the union operator (implicit) and the intersection
...
@@ -435,7 +432,7 @@ import java.util.stream.StreamSupport;
...
@@ -435,7 +432,7 @@ import java.util.stream.StreamSupport;
* <td><tt>[a-e][i-u]</tt></td></tr>
* <td><tt>[a-e][i-u]</tt></td></tr>
* <tr><th>5 </th>
* <tr><th>5 </th>
* <td>Intersection</td>
* <td>Intersection</td>
* <td>
<tt>[a-z&&[aeiou]]</tt>
</td></tr>
* <td>
{@code [a-z&&[aeiou]]}
</td></tr>
* </table></blockquote>
* </table></blockquote>
*
*
* <p> Note that a different set of metacharacters are in effect inside
* <p> Note that a different set of metacharacters are in effect inside
...
@@ -444,8 +441,7 @@ import java.util.stream.StreamSupport;
...
@@ -444,8 +441,7 @@ import java.util.stream.StreamSupport;
* character class, while the expression <tt>-</tt> becomes a range
* character class, while the expression <tt>-</tt> becomes a range
* forming metacharacter.
* forming metacharacter.
*
*
* <a name="lt">
* <h3><a name="lt">Line terminators</a></h3>
* <h4> Line terminators </h4>
*
*
* <p> A <i>line terminator</i> is a one- or two-character sequence that marks
* <p> A <i>line terminator</i> is a one- or two-character sequence that marks
* the end of a line of the input character sequence. The following are
* the end of a line of the input character sequence. The following are
...
@@ -480,11 +476,9 @@ import java.util.stream.StreamSupport;
...
@@ -480,11 +476,9 @@ import java.util.stream.StreamSupport;
* except at the end of input. When in {@link #MULTILINE} mode <tt>$</tt>
* except at the end of input. When in {@link #MULTILINE} mode <tt>$</tt>
* matches just before a line terminator or the end of the input sequence.
* matches just before a line terminator or the end of the input sequence.
*
*
* <a name="cg">
* <h3><a name="cg">Groups and capturing</a></h3>
* <h4> Groups and capturing </h4>
*
*
* <a name="gnumber">
* <h4><a name="gnumber">Group number</a></h4>
* <h5> Group number </h5>
* <p> Capturing groups are numbered by counting their opening parentheses from
* <p> Capturing groups are numbered by counting their opening parentheses from
* left to right. In the expression <tt>((A)(B(C)))</tt>, for example, there
* left to right. In the expression <tt>((A)(B(C)))</tt>, for example, there
* are four such groups: </p>
* are four such groups: </p>
...
@@ -507,8 +501,7 @@ import java.util.stream.StreamSupport;
...
@@ -507,8 +501,7 @@ import java.util.stream.StreamSupport;
* subsequence may be used later in the expression, via a back reference, and
* subsequence may be used later in the expression, via a back reference, and
* may also be retrieved from the matcher once the match operation is complete.
* may also be retrieved from the matcher once the match operation is complete.
*
*
* <a name="groupname">
* <h4><a name="groupname">Group name</a></h4>
* <h5> Group name </h5>
* <p>A capturing group can also be assigned a "name", a <tt>named-capturing group</tt>,
* <p>A capturing group can also be assigned a "name", a <tt>named-capturing group</tt>,
* and then be back-referenced later by the "name". Group names are composed of
* and then be back-referenced later by the "name". Group names are composed of
* the following characters. The first character must be a <tt>letter</tt>.
* the following characters. The first character must be a <tt>letter</tt>.
...
@@ -537,7 +530,7 @@ import java.util.stream.StreamSupport;
...
@@ -537,7 +530,7 @@ import java.util.stream.StreamSupport;
* that do not capture text and do not count towards the group total, or
* that do not capture text and do not count towards the group total, or
* <i>named-capturing</i> group.
* <i>named-capturing</i> group.
*
*
* <h
4> Unicode support </h4
>
* <h
3> Unicode support </h3
>
*
*
* <p> This class is in conformance with Level 1 of <a
* <p> This class is in conformance with Level 1 of <a
* href="http://www.unicode.org/reports/tr18/"><i>Unicode Technical
* href="http://www.unicode.org/reports/tr18/"><i>Unicode Technical
...
@@ -568,18 +561,18 @@ import java.util.stream.StreamSupport;
...
@@ -568,18 +561,18 @@ import java.util.stream.StreamSupport;
* <p>
* <p>
* Scripts, blocks, categories and binary properties can be used both inside
* Scripts, blocks, categories and binary properties can be used both inside
* and outside of a character class.
* and outside of a character class.
*
<a name="usc">
*
* <p>
* <p>
* <b>
Scripts
</b> are specified either with the prefix {@code Is}, as in
* <b>
<a name="usc">Scripts</a>
</b> are specified either with the prefix {@code Is}, as in
* {@code IsHiragana}, or by using the {@code script} keyword (or its short
* {@code IsHiragana}, or by using the {@code script} keyword (or its short
* form {@code sc})as in {@code script=Hiragana} or {@code sc=Hiragana}.
* form {@code sc})as in {@code script=Hiragana} or {@code sc=Hiragana}.
* <p>
* <p>
* The script names supported by <code>Pattern</code> are the valid script names
* The script names supported by <code>Pattern</code> are the valid script names
* accepted and defined by
* accepted and defined by
* {@link java.lang.Character.UnicodeScript#forName(String) UnicodeScript.forName}.
* {@link java.lang.Character.UnicodeScript#forName(String) UnicodeScript.forName}.
*
<a name="ubc">
*
* <p>
* <p>
* <b>
Blocks
</b> are specified with the prefix {@code In}, as in
* <b>
<a name="ubc">Blocks</a>
</b> are specified with the prefix {@code In}, as in
* {@code InMongolian}, or by using the keyword {@code block} (or its short
* {@code InMongolian}, or by using the keyword {@code block} (or its short
* form {@code blk}) as in {@code block=Mongolian} or {@code blk=Mongolian}.
* form {@code blk}) as in {@code block=Mongolian} or {@code blk=Mongolian}.
* <p>
* <p>
...
@@ -587,8 +580,8 @@ import java.util.stream.StreamSupport;
...
@@ -587,8 +580,8 @@ import java.util.stream.StreamSupport;
* accepted and defined by
* accepted and defined by
* {@link java.lang.Character.UnicodeBlock#forName(String) UnicodeBlock.forName}.
* {@link java.lang.Character.UnicodeBlock#forName(String) UnicodeBlock.forName}.
* <p>
* <p>
*
<a name="ucc">
*
* <b>
Categories
</b> may be specified with the optional prefix {@code Is}:
* <b>
<a name="ucc">Categories</a>
</b> may be specified with the optional prefix {@code Is}:
* Both {@code \p{L}} and {@code \p{IsL}} denote the category of Unicode
* Both {@code \p{L}} and {@code \p{IsL}} denote the category of Unicode
* letters. Same as scripts and blocks, categories can also be specified
* letters. Same as scripts and blocks, categories can also be specified
* by using the keyword {@code general_category} (or its short form
* by using the keyword {@code general_category} (or its short form
...
@@ -600,8 +593,8 @@ import java.util.stream.StreamSupport;
...
@@ -600,8 +593,8 @@ import java.util.stream.StreamSupport;
* {@link java.lang.Character Character} class. The category names are those
* {@link java.lang.Character Character} class. The category names are those
* defined in the Standard, both normative and informative.
* defined in the Standard, both normative and informative.
* <p>
* <p>
*
<a name="ubpc">
*
* <b>
Binary properties
</b> are specified with the prefix {@code Is}, as in
* <b>
<a name="ubpc">Binary properties</a>
</b> are specified with the prefix {@code Is}, as in
* {@code IsAlphabetic}. The supported binary properties by <code>Pattern</code>
* {@code IsAlphabetic}. The supported binary properties by <code>Pattern</code>
* are
* are
* <ul>
* <ul>
...
@@ -629,8 +622,8 @@ import java.util.stream.StreamSupport;
...
@@ -629,8 +622,8 @@ import java.util.stream.StreamSupport;
* <table border="0" cellpadding="1" cellspacing="0"
* <table border="0" cellpadding="1" cellspacing="0"
* summary="predefined and posix character classes in Unicode mode">
* summary="predefined and posix character classes in Unicode mode">
* <tr align="left">
* <tr align="left">
* <th
bgcolor="#CCCCFF" align="left" id="
classes">Classes</th>
* <th
align="left" id="predef_
classes">Classes</th>
* <th
bgcolor="#CCCCFF" align="left" id="
matches">Matches</th>
* <th
align="left" id="predef_
matches">Matches</th>
*</tr>
*</tr>
* <tr><td><tt>\p{Lower}</tt></td>
* <tr><td><tt>\p{Lower}</tt></td>
* <td>A lowercase character:<tt>\p{IsLowercase}</tt></td></tr>
* <td>A lowercase character:<tt>\p{IsLowercase}</tt></td></tr>
...
@@ -649,9 +642,9 @@ import java.util.stream.StreamSupport;
...
@@ -649,9 +642,9 @@ import java.util.stream.StreamSupport;
* <tr><td><tt>\p{Graph}</tt></td>
* <tr><td><tt>\p{Graph}</tt></td>
* <td>A visible character: <tt>[^\p{IsWhite_Space}\p{gc=Cc}\p{gc=Cs}\p{gc=Cn}]</tt></td></tr>
* <td>A visible character: <tt>[^\p{IsWhite_Space}\p{gc=Cc}\p{gc=Cs}\p{gc=Cn}]</tt></td></tr>
* <tr><td><tt>\p{Print}</tt></td>
* <tr><td><tt>\p{Print}</tt></td>
* <td>A printable character:
<tt>[\p{Graph}\p{Blank}&&[^\p{Cntrl}]]</tt>
</td></tr>
* <td>A printable character:
{@code [\p{Graph}\p{Blank}&&[^\p{Cntrl}]]}
</td></tr>
* <tr><td><tt>\p{Blank}</tt></td>
* <tr><td><tt>\p{Blank}</tt></td>
* <td>A space or a tab:
<tt>[\p{IsWhite_Space}&&[^\p{gc=Zl}\p{gc=Zp}\x0a\x0b\x0c\x0d\x85]]</tt>
</td></tr>
* <td>A space or a tab:
{@code [\p{IsWhite_Space}&&[^\p{gc=Zl}\p{gc=Zp}\x0a\x0b\x0c\x0d\x85]]}
</td></tr>
* <tr><td><tt>\p{Cntrl}</tt></td>
* <tr><td><tt>\p{Cntrl}</tt></td>
* <td>A control character: <tt>\p{gc=Cc}</tt></td></tr>
* <td>A control character: <tt>\p{gc=Cc}</tt></td></tr>
* <tr><td><tt>\p{XDigit}</tt></td>
* <tr><td><tt>\p{XDigit}</tt></td>
...
@@ -676,9 +669,9 @@ import java.util.stream.StreamSupport;
...
@@ -676,9 +669,9 @@ import java.util.stream.StreamSupport;
* Categories that behave like the java.lang.Character
* Categories that behave like the java.lang.Character
* boolean is<i>methodname</i> methods (except for the deprecated ones) are
* boolean is<i>methodname</i> methods (except for the deprecated ones) are
* available through the same <tt>\p{</tt><i>prop</i><tt>}</tt> syntax where
* available through the same <tt>\p{</tt><i>prop</i><tt>}</tt> syntax where
* the specified property has the name <tt>java<i>methodname</i></tt>.
* the specified property has the name <tt>java<i>methodname</i></tt>
</a>
.
*
*
* <h
4> Comparison to Perl 5 </h4
>
* <h
3> Comparison to Perl 5 </h3
>
*
*
* <p>The <code>Pattern</code> engine performs traditional NFA-based matching
* <p>The <code>Pattern</code> engine performs traditional NFA-based matching
* with ordered alternation as occurs in Perl 5.
* with ordered alternation as occurs in Perl 5.
...
@@ -1023,11 +1016,11 @@ public final class Pattern
...
@@ -1023,11 +1016,11 @@ public final class Pattern
private
transient
boolean
hasSupplementary
;
private
transient
boolean
hasSupplementary
;
/**
/**
* Compiles the given regular expression into a pattern.
</p>
* Compiles the given regular expression into a pattern.
*
*
* @param regex
* @param regex
* The expression to be compiled
* The expression to be compiled
*
*
@return the given regular expression compiled into a pattern
* @throws PatternSyntaxException
* @throws PatternSyntaxException
* If the expression's syntax is invalid
* If the expression's syntax is invalid
*/
*/
...
@@ -1037,7 +1030,7 @@ public final class Pattern
...
@@ -1037,7 +1030,7 @@ public final class Pattern
/**
/**
* Compiles the given regular expression into a pattern with the given
* Compiles the given regular expression into a pattern with the given
* flags.
</p>
* flags.
*
*
* @param regex
* @param regex
* The expression to be compiled
* The expression to be compiled
...
@@ -1049,6 +1042,7 @@ public final class Pattern
...
@@ -1049,6 +1042,7 @@ public final class Pattern
* {@link #LITERAL}, {@link #UNICODE_CHARACTER_CLASS}
* {@link #LITERAL}, {@link #UNICODE_CHARACTER_CLASS}
* and {@link #COMMENTS}
* and {@link #COMMENTS}
*
*
* @return the given regular expression compiled into a pattern with the given flags
* @throws IllegalArgumentException
* @throws IllegalArgumentException
* If bit values other than those corresponding to the defined
* If bit values other than those corresponding to the defined
* match flags are set in <tt>flags</tt>
* match flags are set in <tt>flags</tt>
...
@@ -1062,7 +1056,6 @@ public final class Pattern
...
@@ -1062,7 +1056,6 @@ public final class Pattern
/**
/**
* Returns the regular expression from which this pattern was compiled.
* Returns the regular expression from which this pattern was compiled.
* </p>
*
*
* @return The source of this pattern
* @return The source of this pattern
*/
*/
...
@@ -1084,7 +1077,6 @@ public final class Pattern
...
@@ -1084,7 +1077,6 @@ public final class Pattern
/**
/**
* Creates a matcher that will match the given input against this pattern.
* Creates a matcher that will match the given input against this pattern.
* </p>
*
*
* @param input
* @param input
* The character sequence to be matched
* The character sequence to be matched
...
@@ -1103,7 +1095,7 @@ public final class Pattern
...
@@ -1103,7 +1095,7 @@ public final class Pattern
}
}
/**
/**
* Returns this pattern's match flags.
</p>
* Returns this pattern's match flags.
*
*
* @return The match flags specified when this pattern was compiled
* @return The match flags specified when this pattern was compiled
*/
*/
...
@@ -1133,7 +1125,7 @@ public final class Pattern
...
@@ -1133,7 +1125,7 @@ public final class Pattern
*
*
* @param input
* @param input
* The character sequence to be matched
* The character sequence to be matched
*
*
@return whether or not the regular expression matches on the input
* @throws PatternSyntaxException
* @throws PatternSyntaxException
* If the expression's syntax is invalid
* If the expression's syntax is invalid
*/
*/
...
@@ -1170,9 +1162,9 @@ public final class Pattern
...
@@ -1170,9 +1162,9 @@ public final class Pattern
*
*
* <blockquote><table cellpadding=1 cellspacing=0
* <blockquote><table cellpadding=1 cellspacing=0
* summary="Split examples showing regex, limit, and result">
* summary="Split examples showing regex, limit, and result">
* <tr><th
><P
align="left"><i>Regex </i></th>
* <tr><th align="left"><i>Regex </i></th>
* <th
><P
align="left"><i>Limit </i></th>
* <th align="left"><i>Limit </i></th>
* <th
><P
align="left"><i>Result </i></th></tr>
* <th align="left"><i>Result </i></th></tr>
* <tr><td align=center>:</td>
* <tr><td align=center>:</td>
* <td align=center>2</td>
* <td align=center>2</td>
* <td><tt>{ "boo", "and:foo" }</tt></td></tr>
* <td><tt>{ "boo", "and:foo" }</tt></td></tr>
...
@@ -1253,8 +1245,8 @@ public final class Pattern
...
@@ -1253,8 +1245,8 @@ public final class Pattern
*
*
* <blockquote><table cellpadding=1 cellspacing=0
* <blockquote><table cellpadding=1 cellspacing=0
* summary="Split examples showing regex and result">
* summary="Split examples showing regex and result">
* <tr><th
><P
align="left"><i>Regex </i></th>
* <tr><th align="left"><i>Regex </i></th>
* <th
><P
align="left"><i>Result</i></th></tr>
* <th align="left"><i>Result</i></th></tr>
* <tr><td align=center>:</td>
* <tr><td align=center>:</td>
* <td><tt>{ "boo", "and", "foo" }</tt></td></tr>
* <td><tt>{ "boo", "and", "foo" }</tt></td></tr>
* <tr><td align=center>o</td>
* <tr><td align=center>o</td>
...
...
src/share/classes/java/util/stream/AbstractPipeline.java
浏览文件 @
6693c900
...
@@ -53,11 +53,6 @@ import java.util.function.Supplier;
...
@@ -53,11 +53,6 @@ import java.util.function.Supplier;
* operation, the stream is considered to be consumed, and no more intermediate
* operation, the stream is considered to be consumed, and no more intermediate
* or terminal operations are permitted on this stream instance.
* or terminal operations are permitted on this stream instance.
*
*
* <p>{@code AbstractPipeline} implements a number of methods that are
* specified in {@link BaseStream}, though it does not implement
* {@code BaseStream} directly. Subclasses of {@code AbstractPipeline}
* will generally implement {@code BaseStream}.
*
* @implNote
* @implNote
* <p>For sequential streams, and parallel streams without
* <p>For sequential streams, and parallel streams without
* <a href="package-summary.html#StreamOps">stateful intermediate
* <a href="package-summary.html#StreamOps">stateful intermediate
...
@@ -75,7 +70,7 @@ import java.util.function.Supplier;
...
@@ -75,7 +70,7 @@ import java.util.function.Supplier;
* @since 1.8
* @since 1.8
*/
*/
abstract
class
AbstractPipeline
<
E_IN
,
E_OUT
,
S
extends
BaseStream
<
E_OUT
,
S
>>
abstract
class
AbstractPipeline
<
E_IN
,
E_OUT
,
S
extends
BaseStream
<
E_OUT
,
S
>>
extends
PipelineHelper
<
E_OUT
>
{
extends
PipelineHelper
<
E_OUT
>
implements
BaseStream
<
E_OUT
,
S
>
{
/**
/**
* Backlink to the head of the pipeline chain (self if this is the source
* Backlink to the head of the pipeline chain (self if this is the source
* stage).
* stage).
...
@@ -286,26 +281,20 @@ abstract class AbstractPipeline<E_IN, E_OUT, S extends BaseStream<E_OUT, S>>
...
@@ -286,26 +281,20 @@ abstract class AbstractPipeline<E_IN, E_OUT, S extends BaseStream<E_OUT, S>>
// BaseStream
// BaseStream
/**
@Override
* Implements {@link BaseStream#sequential()}
*/
public
final
S
sequential
()
{
public
final
S
sequential
()
{
sourceStage
.
parallel
=
false
;
sourceStage
.
parallel
=
false
;
return
(
S
)
this
;
return
(
S
)
this
;
}
}
/**
@Override
* Implements {@link BaseStream#parallel()}
*/
public
final
S
parallel
()
{
public
final
S
parallel
()
{
sourceStage
.
parallel
=
true
;
sourceStage
.
parallel
=
true
;
return
(
S
)
this
;
return
(
S
)
this
;
}
}
// Primitive specialization use co-variant overrides, hence is not final
// Primitive specialization use co-variant overrides, hence is not final
/**
@Override
* Implements {@link BaseStream#spliterator()}
*/
public
Spliterator
<
E_OUT
>
spliterator
()
{
public
Spliterator
<
E_OUT
>
spliterator
()
{
if
(
linkedOrConsumed
)
if
(
linkedOrConsumed
)
throw
new
IllegalStateException
(
"stream has already been operated upon"
);
throw
new
IllegalStateException
(
"stream has already been operated upon"
);
...
@@ -331,9 +320,7 @@ abstract class AbstractPipeline<E_IN, E_OUT, S extends BaseStream<E_OUT, S>>
...
@@ -331,9 +320,7 @@ abstract class AbstractPipeline<E_IN, E_OUT, S extends BaseStream<E_OUT, S>>
}
}
}
}
/**
@Override
* Implements {@link BaseStream#isParallel()}
*/
public
final
boolean
isParallel
()
{
public
final
boolean
isParallel
()
{
return
sourceStage
.
parallel
;
return
sourceStage
.
parallel
;
}
}
...
...
src/share/classes/java/util/stream/BaseStream.java
浏览文件 @
6693c900
...
@@ -29,15 +29,13 @@ import java.util.Spliterator;
...
@@ -29,15 +29,13 @@ import java.util.Spliterator;
/**
/**
* Base interface for stream types such as {@link Stream}, {@link IntStream},
* Base interface for stream types such as {@link Stream}, {@link IntStream},
* etc. Contains methods common to all stream types. Many of these methods
* etc. Contains methods common to all stream types.
* are implemented by {@link AbstractPipeline}, even though
* {@code AbstractPipeline} does not directly implement {@code BaseStream}.
*
*
* @param <T> type of stream elements
* @param <T> type of stream elements
* @param <S> type of stream implementing {@code BaseStream}
* @param <S> type of stream implementing {@code BaseStream}
* @since 1.8
* @since 1.8
*/
*/
interface
BaseStream
<
T
,
S
extends
BaseStream
<
T
,
S
>>
{
public
interface
BaseStream
<
T
,
S
extends
BaseStream
<
T
,
S
>>
{
/**
/**
* Returns an iterator for the elements of this stream.
* Returns an iterator for the elements of this stream.
*
*
...
...
test/java/lang/SecurityManager/CheckPackageAccess.java
浏览文件 @
6693c900
...
@@ -22,31 +22,133 @@
...
@@ -22,31 +22,133 @@
*/
*/
/*
/*
* @test
* @test
* @bug 7146431 8000450
* @bug 6741606 7146431 8000450
* @summary Test that internal packages cannot be accessed
* @summary Make sure all restricted packages listed in the package.access
* property in the java.security file are blocked
* @run main/othervm CheckPackageAccess
*/
*/
import
java.security.Security
;
import
java.util.Collections
;
import
java.util.Arrays
;
import
java.util.ArrayList
;
import
java.util.List
;
import
java.util.StringTokenizer
;
/*
* The main benefit of this test is to catch merge errors or other types
* of issues where one or more of the packages are accidentally
* removed. This is why the packages that are known to be restricted have to
* be explicitly listed below.
*/
public
class
CheckPackageAccess
{
public
class
CheckPackageAccess
{
/*
* This array should be updated whenever new packages are added to the
* package.access property in the java.security file
*/
private
static
final
String
[]
packages
=
{
"sun."
,
"com.sun.corba.se.impl."
,
"com.sun.xml.internal."
,
"com.sun.imageio."
,
"com.sun.istack.internal."
,
"com.sun.jmx."
,
"com.sun.proxy."
,
"com.sun.org.apache.bcel.internal."
,
"com.sun.org.apache.regexp.internal."
,
"com.sun.org.apache.xerces.internal."
,
"com.sun.org.apache.xpath.internal."
,
"com.sun.org.apache.xalan.internal.extensions."
,
"com.sun.org.apache.xalan.internal.lib."
,
"com.sun.org.apache.xalan.internal.res."
,
"com.sun.org.apache.xalan.internal.templates."
,
"com.sun.org.apache.xalan.internal.utils."
,
"com.sun.org.apache.xalan.internal.xslt."
,
"com.sun.org.apache.xalan.internal.xsltc.cmdline."
,
"com.sun.org.apache.xalan.internal.xsltc.compiler."
,
"com.sun.org.apache.xalan.internal.xsltc.trax."
,
"com.sun.org.apache.xalan.internal.xsltc.util."
,
"com.sun.org.apache.xml.internal.res."
,
"com.sun.org.apache.xml.internal.security."
,
"com.sun.org.apache.xml.internal.serializer.utils."
,
"com.sun.org.apache.xml.internal.utils."
,
"com.sun.org.glassfish."
,
"com.oracle.xmlns.internal."
,
"com.oracle.webservices.internal."
,
"oracle.jrockit.jfr."
,
"org.jcp.xml.dsig.internal."
,
"jdk.internal."
,
"jdk.nashorn.internal."
,
"jdk.nashorn.tools."
};
public
static
void
main
(
String
[]
args
)
throws
Exception
{
public
static
void
main
(
String
[]
args
)
throws
Exception
{
List
<
String
>
pkgs
=
new
ArrayList
<>(
Arrays
.
asList
(
packages
));
String
osName
=
System
.
getProperty
(
"os.name"
);
if
(
osName
.
contains
(
"OS X"
))
{
pkgs
.
add
(
"apple."
);
// add apple package for OS X
}
else
if
(
osName
.
startsWith
(
"Windows"
))
{
pkgs
.
add
(
"com.sun.java.accessibility."
);
}
List
<
String
>
jspkgs
=
getPackages
(
Security
.
getProperty
(
"package.access"
));
// Sort to ensure lists are comparable
Collections
.
sort
(
pkgs
);
Collections
.
sort
(
jspkgs
);
if
(!
pkgs
.
equals
(
jspkgs
))
{
for
(
String
p
:
pkgs
)
if
(!
jspkgs
.
contains
(
p
))
System
.
out
.
println
(
"In golden set, but not in j.s file: "
+
p
);
for
(
String
p
:
jspkgs
)
if
(!
pkgs
.
contains
(
p
))
System
.
out
.
println
(
"In j.s file, but not in golden set: "
+
p
);
String
[]
pkgs
=
new
String
[]
{
throw
new
RuntimeException
(
"restricted packages are not "
+
"com.sun.corba.se.impl."
,
"consistent with java.security file"
);
"com.sun.org.apache.xerces.internal.utils."
,
}
"com.sun.org.apache.xalan.internal.utils."
};
System
.
setSecurityManager
(
new
SecurityManager
());
SecurityManager
sm
=
new
SecurityManager
();
SecurityManager
sm
=
System
.
getSecurityManager
();
System
.
setSecurityManager
(
sm
);
for
(
String
pkg
:
packages
)
{
for
(
String
pkg
:
pkgs
)
{
String
subpkg
=
pkg
+
"foo"
;
System
.
out
.
println
(
"Checking package access for "
+
pkg
);
try
{
try
{
sm
.
checkPackageAccess
(
pkg
);
sm
.
checkPackageAccess
(
pkg
);
throw
new
Exception
(
"Expected PackageAccess SecurityException not thrown"
);
throw
new
RuntimeException
(
"Able to access "
+
pkg
+
" package"
);
}
catch
(
SecurityException
se
)
{
}
try
{
sm
.
checkPackageAccess
(
subpkg
);
throw
new
RuntimeException
(
"Able to access "
+
subpkg
+
" package"
);
}
catch
(
SecurityException
se
)
{
}
}
catch
(
SecurityException
se
)
{
}
try
{
try
{
sm
.
checkPackageDefinition
(
pkg
);
sm
.
checkPackageDefinition
(
pkg
);
throw
new
Exception
(
"Expected PackageDefinition SecurityException not thrown"
);
throw
new
RuntimeException
(
"Able to define class in "
+
pkg
+
" package"
);
}
catch
(
SecurityException
se
)
{
}
try
{
sm
.
checkPackageDefinition
(
subpkg
);
throw
new
RuntimeException
(
"Able to define class in "
+
subpkg
+
" package"
);
}
catch
(
SecurityException
se
)
{
}
}
catch
(
SecurityException
se
)
{
}
}
}
System
.
out
.
println
(
"Test passed"
);
}
private
static
List
<
String
>
getPackages
(
String
p
)
{
List
<
String
>
packages
=
new
ArrayList
<>();
if
(
p
!=
null
&&
!
p
.
equals
(
""
))
{
StringTokenizer
tok
=
new
StringTokenizer
(
p
,
","
);
while
(
tok
.
hasMoreElements
())
{
String
s
=
tok
.
nextToken
().
trim
();
packages
.
add
(
s
);
}
}
return
packages
;
}
}
}
}
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录