JAVA マルチスレッド プログラミングを知っている人なら誰でも、スレッドを生成するには 2 つの方法があることを知っています。1 つは、クラスが Thread クラスを直接継承し、その run() メソッドを実装する方法です。もう 1 つは、クラスが Runnable インターフェイスを実装し、 run() メソッドを使用して、次の形式のように、このクラスをコンストラクター パラメーターとして使用して新しいスレッドを作成します: Thread t=new Thread(myRunnable)。最後に、Thread クラスの start() メソッドを実行することでスレッドが開始されます。
JAVA では、スレッドの実行が終了すると、つまり run() メソッドを実行した後は再起動できません。この時点で、このスレッド オブジェクトは不要なオブジェクトとなり、ガベージ コレクターによるリサイクルを待っています。次回このスレッドを再度開始する場合は、新しいスレッド オブジェクトを作成して再度開始する必要があります。オブジェクトの頻繁な作成と破棄は、操作効率に影響を与えるだけでなく、不要なスレッド オブジェクトをリサイクルする時間がないため、大量のガベージ メモリが生成される可能性があります。この影響は、ストレージ容量と処理速度が比較的限られているモバイル プラットフォームでは特に大きくなります。 。では、オブジェクトを頻繁に作成したり破棄したりせずに繰り返し開始できるようにスレッド クラスを再設計することはできるでしょうか?
もちろんです。次に、この「再開可能スレッド」クラスの設計を紹介します。
まず第一に、スレッドに実行させたいタスクをスレッドの run() メソッドに直接入れても、とにかく目的を達成できないことを明確にする必要があります。 JAVA スレッド クラスが実行されると、 run() メソッドが完了すると、再度開始することはできません。したがって、唯一の実現可能な方法は、ユーザー プログラム (「ユーザー プロセス」と呼ばれる場合もあります) の run() メソッドを、ユーザー プロセスが実行されるときにスレッドの実際の run() メソッド内の while ループ本体に入れることです。待って 。スレッドを再起動するために restart メソッドが呼び出されると、待機中のスレッドが実際に起動されて、次の while ループが開始されます。大まかな考え方が決まり、次のコードは理解しやすいです:
public class ReusableThread implements Runnable { //线程状态监听者接口 public interface ThreadStateListener { public abstract void onRunOver(ReusableThread thread);//当用户过程执行完毕后调用的方法 } public static final byte STATE_READY=0; //线程已准备好,等待开始用户过程 public static final byte STATE_STARTED=1; //用户过程已启动 public static final byte STATE_DESTROYED=2; //线程最终销毁 byte mState; //标示可重启线程的当前状态 Thread mThread; //实际的主线程对象 Runnable mProc; //用户过程的run()方法定义在mProc中 ThreadStateListener mListener; //状态监听者,可以为null /** Creates a new instance of ReusableThread */ public ReusableThread(Runnable proc) { mProc = proc; mListener = null; mThread = new Thread(this); mState = STATE_READY; } public byte getState() {return mState;} public void setStateListener(ThreadStateListener listener) { mListener = listener; } /**可以在处于等待状态时调用该方法重设用户过程*/ public synchronized boolean setProcedure(Runnable proc) { if (mState == STATE_READY) { mProc = proc; return true; } else return false; } /**开始执行用户过程*/ public synchronized boolean start() { if (mState == STATE_READY) { mState = STATE_STARTED; if (!mThread.isAlive()) mThread.start(); notify(); //唤醒因用户过程执行结束而进入等待中的主线程 return true; } else return false; } /**结束整个线程,销毁主线程对象。之后将不可再次启动*/ public synchronized void destroy() { mState = STATE_DESTROYED; notify(); mThread = null; } public void run() { while (true) { synchronized (this) { try { while (mState != STATE_STARTED) { if (mState == STATE_DESTROYED) return; wait(); } } catch(Exception e) {e.printStackTrace();} } if (mProc != null) mProc.run(); if (mListener != null) mListener.onRunOver(this); //当用户过程结束后,执行监听者的onRunOver方法 synchronized (this) { if (mState == STATE_DESTROYED) return; mState = STATE_READY; } } } }
コードは理解しやすいですよね。ただし、「ステータス リスナー」インターフェイスが存在する理由を説明してください。追加の処理を実行できるように、ユーザー プロセスの終了後にタイムリーな通知を取得したい場合があります。この場合、ステータス リスナーの onRunOver メソッドが役立ちます。直感的な例としては、以下で説明する「スレッド プール」クラスでは、ユーザー プロセスの実行後に再起動可能なスレッドを自動的にプールに戻す必要があります。このとき、プールに戻るアクションを onRunOver メソッドに配置できます。 、そのパラメータは再起動可能なスレッド オブジェクトであるため、パラメータで示されたオブジェクトはスレッド プールにリサイクルできます。
スレッド プール クラスに関しては、実際には前述のオブジェクト プール クラスのサブクラスであり、その中のすべてのオブジェクトは ReusableThread クラスに属します。さらに、ReusableThread.ThreadStateListener インターフェイスを実装しているので、ユーザー プロセスの終了時に通知を受け、スレッドをリサイクルする作業を実行できます。
public class ThreadPool extends ObjectPool implements ReusableThread.ThreadStateListener { public static final int DefaultNumThreads = 16; //默认池容量 public ReusableThread getThread() { return (ReusableThread)fetch(); } public void onRunOver(ReusableThread thread) { recycle(thread); //当用户过程结束时,回收线程 } private void init(int size) { ReusableThread thread; //初始化线程池内容 for (int i=0; i<size; i++) { thread = new ReusableThread(null); thread.setStateListener(this); setElementAt(thread, i); } } public ThreadPool(int size) { super(size); init(size); } public ThreadPool() { super(DefaultNumThreads); init(DefaultNumThreads); } }
もちろん、追加する必要がある関数がいくつかあります。通常のスレッドよりスレッドが 1 つだけ多いため、再起動可能な「拡張」スレッド クラスの場合、スレッドの sleep() など、元の Thread クラスの関数も使用できる必要があります。ただし、これらは比較的単純なので、ここでは省略します。
以下のテストプログラムを書きます。スレッド プール クラスを使用する代わりに、オブジェクト プール内のオブジェクトが属するクラス CharEmitter で Runnable インターフェイスとスレッドを実装し、オブジェクト プール クラスと再起動可能なスレッド クラスの結合テストを実行する予定です。ステータス リスナー インターフェイス。スレッド プール オブジェクトには含まれないが、独立して使用される再起動可能なスレッド メンバー オブジェクトが含まれます。このスレッド (CharEmitter クラスで定義) のユーザー プロセスが終了すると、onRunOver メソッドは、この CharEmitter オブジェクトをプールにリサイクルするアクションを実行します。これは、オブジェクト プールとの違いは onRunOver でリサイクル アクションを実行することであるため、スレッド プール クラスを間接的にテストする役割も果たします。
わかりやすくするために、コードに直接アクセスすることをお勧めします:
TestThreadPool.java :
/**字符放射器*/ class CharEmitter implements Runnable, ReusableThread.ThreadStateListener { char c; //被发射的字符 boolean[] isEmitting; //标示某字符是否正被发射(直接以字符对应的ASCII码作下标索引) ReusableThread thread; //可重启线程对象 ObjectPool myHomePool; //为知道应把自己回收到哪里,需要保存一个到自己所在对象池的引用 CharEmitter(ObjectPool container, boolean[] isCharEmitting) { isEmitting=isCharEmitting; myHomePool=container; thread=new ReusableThread(this); //新建可重启线程对象,设其用户过程为CharEmitter类自己定义的 } /**开始“发射”字符*/ public void emit(char ch) { //字符被要求只能是'0'到'9'之间的数字字符 if (ch>='0' && ch<='9') { c=ch; } else c=' '; thread.start(); //启动线程 } public void run() { if (c==' ') return; //若不是数字字符直接结束 //为便于观察,不同数字之前的空格数目不同,以便将其排在不同列上 int spaceLen=c-'0'; StringBuffer s=new StringBuffer(spaceLen+1); for (int i=0; i<spaceLen; i++) s.append(' '); s.append(c); while (isEmitting[c]) { System.out.println(s); //不断地向屏幕写字符 } } /**实现线程状态监听者接口中的方法*/ public void onRunOver(ReusableThread t) { myHomePool.recycle(this); //回收自身入池 } } public class TestThreadPool { public static void main(String[] args) { // TODO Auto-generated method stub //标示字符是否正被发射的标志变量数组 boolean[] isEmitting=new boolean[256]; for (int i=0; i<256; i++) isEmitting[i]=false; ObjectPool emitters=new ObjectPool(10); //新建对象池,容量为10 for (int i=0; i<10; i++) { //用CharEmitter对象填满池子 emitters.setElementAt(new CharEmitter(emitters, isEmitting), i); } byte[] c=new byte[1]; CharEmitter emitter; while(true) { try { System.in.read(c); //从键盘读入一个字符,以回车键表示输入结束 } catch(Exception e) {e.printStackTrace();} if (isEmitting[c[0]]) { isEmitting[c[0]]=false; //若字符正被发射,则结束其发射 } else { isEmitting[c[0]]=true; emitter=(CharEmitter)emitters.fetch(); //向池中索取一个CharEmitter对象 emitter.emit((char)c[0]); //发射用户输入的字符 } } } }
実行後、キーボードから 0 から 9 までの任意の数字を入力して Enter キーを押すと、画面がスクロールし続けます。番号を表示するには、同じ番号を再度入力すると、番号は表示されなくなります。複数の数値が同時に送信されると、異なる数値の表示が交互に表示されることが明らかにわかります。これはまさに、スレッド間での仮想マシンのスケジューリングの結果です。実行結果は、設計したクラス関数が完全に正しいことを示しています。
後で説明する J2ME の Bluetooth 通信の補助クラスでは、スレッド プールと再起動可能なスレッドがかけがえのない役割を果たすことがわかります。
上記の Java 再起動可能スレッドとスレッド プール クラスの設計 (詳細な説明) は、編集者によって共有されたすべての内容です。参考にしていただければ幸いです。また、PHP 中国語 Web サイトをサポートしていただければ幸いです。
Java の再起動可能なスレッドとスレッド プール クラスの設計に関する関連記事 (詳細な説明) については、PHP 中国語 Web サイトに注目してください。

Javaは、プラットフォームの独立性により、エンタープライズレベルのアプリケーションで広く使用されています。 1)プラットフォームの独立性は、Java Virtual Machine(JVM)を介して実装されているため、Javaをサポートする任意のプラットフォームでコードを実行できます。 2)クロスプラットフォームの展開と開発プロセスを簡素化し、柔軟性とスケーラビリティを高めます。 3)ただし、パフォーマンスの違いとサードパーティライブラリの互換性に注意を払い、純粋なJavaコードやクロスプラットフォームテストの使用などのベストプラクティスを採用する必要があります。

javaplaysasificanificantduetduetoitsplatformindepence.1)itallowscodetobewrittendunonvariousdevices.2)java'secosystemprovidesutionforiot.3)そのセキュリティフィートルセンハンス系

TheSolution to HandlefilepathsaCrosswindossandlinuxinjavaistousepaths.get()fromthejava.nio.filepackage.1)usesystem.getProperty( "user.dir")およびhearterativepathtoconstructurctthefilepath.2)

java'splatformentepenceissificAntiveSifcuseDeverowsDevelowSowRitecodeOdeonceantoniTONAnyPlatformwsajvm.これは「writeonce、runanywhere」(wora)adportoffers:1)クロスプラットフォームの複雑性、deploymentacrossdiferentososwithusisues; 2)re

Javaは、クロスサーバーWebアプリケーションの開発に適しています。 1)Javaの「Write and、Run Averywhere」哲学は、JVMをサポートするあらゆるプラットフォームでコードを実行します。 2)Javaには、開発プロセスを簡素化するために、SpringやHibernateなどのツールを含む豊富なエコシステムがあります。 3)Javaは、パフォーマンスとセキュリティにおいて優れたパフォーマンスを発揮し、効率的なメモリ管理と強力なセキュリティ保証を提供します。

JVMは、バイトコード解釈、プラットフォームに依存しないAPI、動的クラスの負荷を介してJavaのWORA機能を実装します。 2。標準API抽象オペレーティングシステムの違い。 3.クラスは、実行時に動的にロードされ、一貫性を確保します。

Javaの最新バージョンは、JVMの最適化、標準的なライブラリの改善、サードパーティライブラリサポートを通じて、プラットフォーム固有の問題を効果的に解決します。 1)Java11のZGCなどのJVM最適化により、ガベージコレクションのパフォーマンスが向上します。 2)Java9のモジュールシステムなどの標準的なライブラリの改善は、プラットフォーム関連の問題を削減します。 3)サードパーティライブラリは、OpenCVなどのプラットフォーム最適化バージョンを提供します。

JVMのバイトコード検証プロセスには、4つの重要な手順が含まれます。1)クラスファイル形式が仕様に準拠しているかどうかを確認し、2)バイトコード命令の有効性と正確性を確認し、3)データフロー分析を実行してタイプの安全性を確保し、検証の完全性とパフォーマンスのバランスをとる。これらの手順を通じて、JVMは、安全で正しいバイトコードのみが実行されることを保証し、それによりプログラムの完全性とセキュリティを保護します。


ホットAIツール

Undresser.AI Undress
リアルなヌード写真を作成する AI 搭載アプリ

AI Clothes Remover
写真から衣服を削除するオンライン AI ツール。

Undress AI Tool
脱衣画像を無料で

Clothoff.io
AI衣類リムーバー

Video Face Swap
完全無料の AI 顔交換ツールを使用して、あらゆるビデオの顔を簡単に交換できます。

人気の記事

ホットツール

SublimeText3 中国語版
中国語版、とても使いやすい

MantisBT
Mantis は、製品の欠陥追跡を支援するために設計された、導入が簡単な Web ベースの欠陥追跡ツールです。 PHP、MySQL、Web サーバーが必要です。デモおよびホスティング サービスをチェックしてください。

MinGW - Minimalist GNU for Windows
このプロジェクトは osdn.net/projects/mingw に移行中です。引き続きそこでフォローしていただけます。 MinGW: GNU Compiler Collection (GCC) のネイティブ Windows ポートであり、ネイティブ Windows アプリケーションを構築するための自由に配布可能なインポート ライブラリとヘッダー ファイルであり、C99 機能をサポートする MSVC ランタイムの拡張機能が含まれています。すべての MinGW ソフトウェアは 64 ビット Windows プラットフォームで実行できます。

mPDF
mPDF は、UTF-8 でエンコードされた HTML から PDF ファイルを生成できる PHP ライブラリです。オリジナルの作者である Ian Back は、Web サイトから「オンザフライ」で PDF ファイルを出力し、さまざまな言語を処理するために mPDF を作成しました。 HTML2FPDF などのオリジナルのスクリプトよりも遅く、Unicode フォントを使用すると生成されるファイルが大きくなりますが、CSS スタイルなどをサポートし、多くの機能強化が施されています。 RTL (アラビア語とヘブライ語) や CJK (中国語、日本語、韓国語) を含むほぼすべての言語をサポートします。ネストされたブロックレベル要素 (P、DIV など) をサポートします。

AtomエディタMac版ダウンロード
最も人気のあるオープンソースエディター

ホットトピック









