Java Reference
In-Depth Information
public
Integer
call
()
{
int
max
=
Integer
.
MIN_VALUE
;
for
(
int
i
=
start
;
i
<
end
;
i
++)
{
if
(
data
[
i
]
>
max
)
max
=
data
[
i
];
}
return
max
;
}
}
Although you could invoke the
call()
method directly, that is not its purpose. Instead,
you submit
Callable
objects to an
Executor
that spins up a thread for each one. (There
are other strategies an
Executor
could use—for instance, it could use a single thread to
invoke the callables in order—but one thread per callable is a good strategy for this
problem.)
Example 3-10
demonstrates.
Example 3-10. MultithreadedMaxFinder
import
java.util.concurrent.*
;
public
class
MultithreadedMaxFinder
{
public
static
int
max
(
int
[]
data
)
throws
InterruptedException
,
ExecutionException
{
if
(
data
.
length
==
1
)
{
return
data
[
0
];
}
else
if
(
data
.
length
==
0
)
{
throw
new
IllegalArgumentException
();
}
// split the job into 2 pieces
FindMaxTask
task1
=
new
FindMaxTask
(
data
,
0
,
data
.
length
/
2
);
FindMaxTask
task2
=
new
FindMaxTask
(
data
,
data
.
length
/
2
,
data
.
length
);
// spawn 2 threads
ExecutorService
service
=
Executors
.
newFixedThreadPool
(
2
);
Future
<
Integer
>
future1
=
service
.
submit
(
task1
);
Future
<
Integer
>
future2
=
service
.
submit
(
task2
);
return
Math
.
max
(
future1
.
get
(),
future2
.
get
());
}
}
Each subarray is searched at the same time, so on suitable hardware and a large input
this program can run almost twice as fast. Nonetheless, the code is almost as simple and
straightforward as finding the maximum in the first half of the array and then finding
the maximum in the second half of the array, without ever worrying about threads or
asynchronicity. However, there's one key difference. In the last statement of
Example 3-10
, when
future1.get()
is called, the method blocks and waits for the first