jpskill.com
🛠️ 開発・MCP コミュニティ

tokio

Rustの非同期ランタイムであるTokioのエキスパートとして、タスクスケジューラや非同期I/O、チャネルなどを活用し、高性能なネットワークアプリケーションや並行処理サービスを構築し、メモリ消費を抑えつつ大量の接続を処理するSkill。

📜 元の英語説明(参考)

You are an expert in Tokio, the asynchronous runtime for Rust that powers most of the Rust async ecosystem. You help developers build high-performance network applications, concurrent services, and I/O-bound systems using Tokio's task scheduler, async I/O primitives, channels, timers, and synchronization utilities — handling millions of concurrent connections with minimal memory overhead.

🇯🇵 日本人クリエイター向け解説

一言でいうと

Rustの非同期ランタイムであるTokioのエキスパートとして、タスクスケジューラや非同期I/O、チャネルなどを活用し、高性能なネットワークアプリケーションや並行処理サービスを構築し、メモリ消費を抑えつつ大量の接続を処理するSkill。

※ jpskill.com 編集部が日本のビジネス現場向けに補足した解説です。Skill本体の挙動とは独立した参考情報です。

⚡ おすすめ: コマンド1行でインストール(60秒)

下記のコマンドをコピーしてターミナル(Mac/Linux)または PowerShell(Windows)に貼り付けてください。 ダウンロード → 解凍 → 配置まで全自動。

🍎 Mac / 🐧 Linux
mkdir -p ~/.claude/skills && cd ~/.claude/skills && curl -L -o tokio.zip https://jpskill.com/download/15487.zip && unzip -o tokio.zip && rm tokio.zip
🪟 Windows (PowerShell)
$d = "$env:USERPROFILE\.claude\skills"; ni -Force -ItemType Directory $d | Out-Null; iwr https://jpskill.com/download/15487.zip -OutFile "$d\tokio.zip"; Expand-Archive "$d\tokio.zip" -DestinationPath $d -Force; ri "$d\tokio.zip"

完了後、Claude Code を再起動 → 普通に「動画プロンプト作って」のように話しかけるだけで自動発動します。

💾 手動でダウンロードしたい(コマンドが難しい人向け)
  1. 1. 下の青いボタンを押して tokio.zip をダウンロード
  2. 2. ZIPファイルをダブルクリックで解凍 → tokio フォルダができる
  3. 3. そのフォルダを C:\Users\あなたの名前\.claude\skills\(Win)または ~/.claude/skills/(Mac)へ移動
  4. 4. Claude Code を再起動

⚠️ ダウンロード・利用は自己責任でお願いします。当サイトは内容・動作・安全性について責任を負いません。

🎯 このSkillでできること

下記の説明文を読むと、このSkillがあなたに何をしてくれるかが分かります。Claudeにこの分野の依頼をすると、自動で発動します。

📦 インストール方法 (3ステップ)

  1. 1. 上の「ダウンロード」ボタンを押して .skill ファイルを取得
  2. 2. ファイル名の拡張子を .skill から .zip に変えて展開(macは自動展開可)
  3. 3. 展開してできたフォルダを、ホームフォルダの .claude/skills/ に置く
    • · macOS / Linux: ~/.claude/skills/
    • · Windows: %USERPROFILE%\.claude\skills\

Claude Code を再起動すれば完了。「このSkillを使って…」と話しかけなくても、関連する依頼で自動的に呼び出されます。

詳しい使い方ガイドを見る →
最終更新
2026-05-18
取得日時
2026-05-18
同梱ファイル
1

📖 Skill本文(日本語訳)

※ 原文(英語/中国語)を Gemini で日本語化したものです。Claude 自身は原文を読みます。誤訳がある場合は原文をご確認ください。

Tokio — Rust のための非同期ランタイム

あなたは Tokio のエキスパートです。Tokio は Rust の非同期ランタイムであり、Rust の非同期エコシステムの大部分を支えています。Tokio のタスクスケジューラ、非同期 I/O プリミティブ、チャネル、タイマー、および同期ユーティリティを使用して、開発者が高性能なネットワークアプリケーション、並行サービス、および I/O バウンドシステムを構築するのを支援します。これにより、最小限のメモリオーバーヘッドで数百万の同時接続を処理できます。

主要な機能

非同期タスク

use tokio::time::{sleep, Duration};
use tokio::task;

#[tokio::main]
async fn main() {
    // 並行タスクの生成
    let handle1 = task::spawn(async {
        sleep(Duration::from_secs(1)).await;
        "Task 1 done"
    });

    let handle2 = task::spawn(async {
        sleep(Duration::from_millis(500)).await;
        "Task 2 done"
    });

    // 両方の待機
    let (r1, r2) = tokio::join!(handle1, handle2);
    println!("{}, {}", r1.unwrap(), r2.unwrap());

    // 最初に完了するものを選択
    tokio::select! {
        val = async { sleep(Duration::from_secs(1)).await; "slow" } => {
            println!("Got: {val}");
        }
        val = async { sleep(Duration::from_millis(100)).await; "fast" } => {
            println!("Got: {val}");
        }
    }

    // 専用のスレッドプールでブロッキング処理(CPU 集中型)を生成
    let result = task::spawn_blocking(|| {
        heavy_computation()                // 非同期ランタイムをブロックしません
    }).await.unwrap();
}

チャネル

use tokio::sync::{mpsc, broadcast, oneshot, watch};

// mpsc: 複数のプロデューサー、単一のコンシューマー
let (tx, mut rx) = mpsc::channel::<String>(100);  // バッファサイズ 100
let tx2 = tx.clone();

task::spawn(async move { tx.send("hello".into()).await.unwrap(); });
task::spawn(async move { tx2.send("world".into()).await.unwrap(); });

while let Some(msg) = rx.recv().await {
    println!("Got: {msg}");
}

// broadcast: 複数のプロデューサー、複数のコンシューマー
let (tx, _) = broadcast::channel::<String>(100);
let mut rx1 = tx.subscribe();
let mut rx2 = tx.subscribe();
tx.send("event".into()).unwrap();
// rx1 と rx2 の両方が "event" を受信します

// oneshot: 単一の値、単一の使用 (リクエスト-レスポンス)
let (tx, rx) = oneshot::channel::<String>();
tx.send("response".into()).unwrap();
let val = rx.await.unwrap();

// watch: 更新および監視できる単一の値
let (tx, mut rx) = watch::channel("initial".to_string());
tx.send("updated".into()).unwrap();
rx.changed().await.unwrap();

TCP サーバー

use tokio::net::TcpListener;
use tokio::io::{AsyncReadExt, AsyncWriteExt};

#[tokio::main]
async fn main() -> std::io::Result<()> {
    let listener = TcpListener::bind("0.0.0.0:8080").await?;

    loop {
        let (mut socket, addr) = listener.accept().await?;
        println!("New connection from {addr}");

        tokio::spawn(async move {
            let mut buf = vec![0u8; 1024];
            loop {
                let n = match socket.read(&mut buf).await {
                    Ok(0) => return,       // 接続が閉じられました
                    Ok(n) => n,
                    Err(e) => { eprintln!("Read error: {e}"); return; }
                };
                if socket.write_all(&buf[..n]).await.is_err() {
                    return;                // 書き込みエラー
                }
            }
        });
    }
}

同期

use tokio::sync::{Mutex, RwLock, Semaphore};
use std::sync::Arc;

// 非同期 Mutex (待機中に yield し、スレッドをブロックしません)
let data = Arc::new(Mutex::new(vec![1, 2, 3]));
let data_clone = data.clone();
tokio::spawn(async move {
    let mut lock = data_clone.lock().await;
    lock.push(4);
});

// RwLock: 複数のリーダー OR 単一のライター
let cache = Arc::new(RwLock::new(HashMap::new()));
let read = cache.read().await;             // 非排他的
let mut write = cache.write().await;       // 排他的

// Semaphore: 並行処理の制限
let semaphore = Arc::new(Semaphore::new(10));  // 最大 10 並行
let permit = semaphore.acquire().await.unwrap();
// ... 処理を実行 ...
drop(permit);                              // 解放

インストール

[dependencies]
tokio = { version = "1", features = ["full"] }
# または選択的に: features = ["rt-multi-thread", "macros", "net", "io-util", "time", "sync"]

ベストプラクティス

  1. ランタイムをブロックしない — CPU 集中型または同期 I/O には spawn_blocking を使用します。非同期スレッドのブロッキングは、他のタスクを飢餓状態にします。
  2. 通信にはチャネルを使用する — 作業キューには mpsc、イベントには broadcast、設定の更新には watch を使用します。
  3. 競合には select を使用するtokio::select! は最初に完了する future を選択します。タイムアウトとキャンセルに最適です。
  4. Async Mutex vs std Mutex.await をまたいでロックを保持する場合は tokio::sync::Mutex を使用します。短い同期専用のロックには std Mutex を使用します。
  5. バックプレッシャーにはセマフォを使用する — 同時データベースクエリ、HTTP リクエスト、またはファイル操作を制限します。
  6. グレースフルシャットダウンtokio::signal::ctrl_c() + キャンセルトークンを使用して、終了前に作業を完了させます。
  7. ランタイム構成 — デフォルトには #[tokio::main] を使用します。カスタムスレッド数とスタックサイズには runtime::Builder を使用します。
  8. トレース統合 — Tokio で tracing クレートを使用します。スパンは非同期タスクの境界を越えて自動的に伝播されます。
📜 原文 SKILL.md(Claudeが読む英語/中国語)を展開

Tokio — Async Runtime for Rust

You are an expert in Tokio, the asynchronous runtime for Rust that powers most of the Rust async ecosystem. You help developers build high-performance network applications, concurrent services, and I/O-bound systems using Tokio's task scheduler, async I/O primitives, channels, timers, and synchronization utilities — handling millions of concurrent connections with minimal memory overhead.

Core Capabilities

Async Tasks

use tokio::time::{sleep, Duration};
use tokio::task;

#[tokio::main]
async fn main() {
    // Spawn concurrent tasks
    let handle1 = task::spawn(async {
        sleep(Duration::from_secs(1)).await;
        "Task 1 done"
    });

    let handle2 = task::spawn(async {
        sleep(Duration::from_millis(500)).await;
        "Task 2 done"
    });

    // Await both
    let (r1, r2) = tokio::join!(handle1, handle2);
    println!("{}, {}", r1.unwrap(), r2.unwrap());

    // Select first to complete
    tokio::select! {
        val = async { sleep(Duration::from_secs(1)).await; "slow" } => {
            println!("Got: {val}");
        }
        val = async { sleep(Duration::from_millis(100)).await; "fast" } => {
            println!("Got: {val}");
        }
    }

    // Spawn blocking work (CPU-intensive) on dedicated thread pool
    let result = task::spawn_blocking(|| {
        heavy_computation()                // Won't block async runtime
    }).await.unwrap();
}

Channels

use tokio::sync::{mpsc, broadcast, oneshot, watch};

// mpsc: Multiple producers, single consumer
let (tx, mut rx) = mpsc::channel::<String>(100);  // Buffer size 100
let tx2 = tx.clone();

task::spawn(async move { tx.send("hello".into()).await.unwrap(); });
task::spawn(async move { tx2.send("world".into()).await.unwrap(); });

while let Some(msg) = rx.recv().await {
    println!("Got: {msg}");
}

// broadcast: Multiple producers, multiple consumers
let (tx, _) = broadcast::channel::<String>(100);
let mut rx1 = tx.subscribe();
let mut rx2 = tx.subscribe();
tx.send("event".into()).unwrap();
// Both rx1 and rx2 receive "event"

// oneshot: Single value, single use (request-response)
let (tx, rx) = oneshot::channel::<String>();
tx.send("response".into()).unwrap();
let val = rx.await.unwrap();

// watch: Single value that can be updated and observed
let (tx, mut rx) = watch::channel("initial".to_string());
tx.send("updated".into()).unwrap();
rx.changed().await.unwrap();

TCP Server

use tokio::net::TcpListener;
use tokio::io::{AsyncReadExt, AsyncWriteExt};

#[tokio::main]
async fn main() -> std::io::Result<()> {
    let listener = TcpListener::bind("0.0.0.0:8080").await?;

    loop {
        let (mut socket, addr) = listener.accept().await?;
        println!("New connection from {addr}");

        tokio::spawn(async move {
            let mut buf = vec![0u8; 1024];
            loop {
                let n = match socket.read(&mut buf).await {
                    Ok(0) => return,       // Connection closed
                    Ok(n) => n,
                    Err(e) => { eprintln!("Read error: {e}"); return; }
                };
                if socket.write_all(&buf[..n]).await.is_err() {
                    return;                // Write error
                }
            }
        });
    }
}

Synchronization

use tokio::sync::{Mutex, RwLock, Semaphore};
use std::sync::Arc;

// Async Mutex (yields while waiting, doesn't block thread)
let data = Arc::new(Mutex::new(vec![1, 2, 3]));
let data_clone = data.clone();
tokio::spawn(async move {
    let mut lock = data_clone.lock().await;
    lock.push(4);
});

// RwLock: Multiple readers OR single writer
let cache = Arc::new(RwLock::new(HashMap::new()));
let read = cache.read().await;             // Non-exclusive
let mut write = cache.write().await;       // Exclusive

// Semaphore: Limit concurrency
let semaphore = Arc::new(Semaphore::new(10));  // Max 10 concurrent
let permit = semaphore.acquire().await.unwrap();
// ... do work ...
drop(permit);                              // Release

Installation

[dependencies]
tokio = { version = "1", features = ["full"] }
# Or selectively: features = ["rt-multi-thread", "macros", "net", "io-util", "time", "sync"]

Best Practices

  1. Don't block the runtime — Use spawn_blocking for CPU-intensive or synchronous I/O; blocking async threads starves other tasks
  2. Use channels for communication — mpsc for work queues, broadcast for events, watch for config updates
  3. Select for racingtokio::select! picks the first future to complete; great for timeouts and cancellation
  4. Async Mutex vs std Mutex — Use tokio::sync::Mutex when holding lock across .await; std Mutex for short, sync-only locks
  5. Semaphores for backpressure — Limit concurrent database queries, HTTP requests, or file operations
  6. Graceful shutdown — Use tokio::signal::ctrl_c() + cancellation tokens to drain work before exiting
  7. Runtime configuration — Use #[tokio::main] for defaults; runtime::Builder for custom thread counts and stack sizes
  8. Tracing integration — Use tracing crate with Tokio; spans propagate across async task boundaries automatically