single thread executor
Michael Bien
mbien42 at gmail.com
Sun Sep 6 08:12:20 UTC 2020
it might help to think of it being two layers. You have plain old java
threads which map to OS threads ("real" threads) and the new virtual
threads.
Virtual threads can only make progress when they are mounted on carrier
threads, which are "real" threads. They add a nice feature however:
concurrent waiting (for resources) without blocking a carrier - which is
a big deal.
to setup everything, carriers + virtuals:
|// plain old thread factory and thread pool using the new builder
ThreadFactory carrierTF = Thread.builder().name("carrier#",
0).factory(); ExecutorService carrierPool =
Executors.newFixedThreadPool( CARRIER_THREAD_COUNT, carrierTF);|
|// factory for virtual threads scheduled on the carrier pool
ThreadFactory virtualTF = Thread.builder() .virtual(carrierPool)
.name("virtual#", 0).factory(); // thread executor will spawn a new
virtual thread for each task |||ExecutorService |executor = Executors.newThreadExecutor(virtualTF);|
in a lot of cases you probably won't have to worry about carrier threads
since it is already set up for you.
for example this will schedule a new virtual thread on the default
scheduler, which is a ForkJoinPool.
|Thread.startVirtualThread(() -> { System.out.println("Hello Loom from
"+Thread.currentThread()+"!"); });|
hope this helps a bit,
michael
- - -
mbien.dev
On 05.09.20 20:14, Miguel Ping wrote:
> Yeah I was about to reply exactly this.
>
> I always thought I knew basic executors, but now I find the api confusing:
> I create a ThreadExecutor that runs off a ThreadFactory (so far so good)
> that is built using virtual threads using a singleThreadExecutor.
> It's a bit confusing to see two executors here, but I guess the
> newThreadExecutor is just wrapping the threadFactory.
>
> Anyway, thanks alot for replying, especially on a saturday.
> I'm anxiously looking forward to continuing experimenting with Loom.
>
> Have a nice weekend.
>
> On Sat, Sep 5, 2020 at 6:02 PM Ron Pressler <ron.pressler at oracle.com> wrote:
>
>> Correction:
>>
>> It should be Executors.newThreadExecutor(tf) rather than
>> Executors.newUnboundedExecutor(tf).
>> The latter was the old API method, which has been renamed to the former.
>>
>> — Ron
>>
>>
>> On 4 September 2020 at 18:50:27, Ron Pressler (ron.pressler at oracle.com)
>> wrote:
>>
>> Remember, you want multiple virtual threads, but use only on platform
>> thread to schedule them. So you need to pass the single-thread executor
>> as the virtual thread scheduler:
>>
>> ThreadFactory tf =
>> Thread.builder().virtual(Executors.newSingleThreadExecutor()).factory();
>>
>> And then you can use the thread factory directly to create virtual
>> threads,
>> or use it like so:
>>
>> ExecutorService e = Executors.newUnboundedExecutor(tf);
>>
>> - Ron
>>
>>
>> On 4 September 2020 at 18:21:45, Miguel Ping (miguel.ping at gmail.com)
>> wrote:
>>
>> Hi all,
>>
>> I was experimenting with single thread executor and loom, and I was
>> expecting that if I have two tasks where the first call goes through
>> Socket.read, loom would schedule the second one. I'm pretty sure I'm doing
>> something wrong.
>>
>> Here's the output I got (I was expecting "Hello world" to appear before
>> "Connected!"; the program only concludes after I Ctrl+C the netcat
>> process):
>>
>>
>> $ nc -p 5555 -kl
>>
>> -- output --
>> sleeping 1s
>> Connected!
>> Hello world
>>
>> -- java --
>>
>> import java.net.InetSocketAddress;
>> import java.nio.ByteBuffer;
>> import java.nio.channels.SocketChannel;
>> import java.util.Arrays;
>> import java.util.concurrent.Callable;
>> import java.util.concurrent.Executors;
>>
>> public class Test {
>>
>> public static String block() {
>> // nc -p 5555 -kl
>> try {
>> System.out.println("sleeping 1s");
>> Thread.sleep(1000);
>> var socket = SocketChannel.open();
>> socket.connect(new InetSocketAddress("localhost", 5555));
>> System.out.println("Connected!");
>> socket.read(ByteBuffer.allocate(10)); // I was hoping this would allow the
>> other task to be scheduled
>> return "End";
>> } catch (Exception e) {
>> e.printStackTrace();
>> return "Failed";
>> }
>> }
>>
>> public static String print() {
>> System.out.println("Hello world");
>> return "Printed";
>> }
>>
>> public static void main(String[] args) throws Throwable {
>> var e = Executors.newFixedThreadPool(1,
>> Thread.builder().virtual().factory());
>> Callable<String> t1 = Test::block;
>> Callable<String> t2 = Test::print;
>>
>> var tasks = Arrays.asList(t1, t2);
>> var fut = e.invokeAll(tasks);
>> }
>> }
>>
>> --
>> Thanks
>>
>>
More information about the loom-dev
mailing list