Heim >Java >javaLernprogramm >Die Verwendung von Java-Parallelitätsthreads und das Erstellen von Startthreads
Threads sind Ausführungsthreads im Programm. Die Java Virtual Machine ermöglicht die Parallelität von Anwendungen. Führen Sie mehrere Threads aus.
Jeder Thread hat eine Priorität und die Ausführung von Threads mit hoher Priorität hat Vorrang vor Threads mit niedriger Priorität. Jeder Thread kann als Daemon markiert sein oder auch nicht. Wenn in einem Thread ausgeführter Code ein neues Thread-Objekt erstellt, wird die anfängliche Priorität des neuen Threads auf die Priorität des erstellenden Threads festgelegt, und der neue Thread ist genau dann ein Daemon, wenn der erstellende Thread ein Daemon-Thread ist.
Wenn die Java Virtual Machine startet, gibt es normalerweise einen einzelnen Nicht-Daemon-Thread (der normalerweise die Hauptmethode einer bestimmten Klasse aufruft). Die Java Virtual Machine führt den Thread so lange aus, bis eine der folgenden Bedingungen eintritt:
1. Die Exit-Methode der Runtime-Klasse wird aufgerufen und der Sicherheitsmanager lässt den Exit-Vorgang zu.
2. Alle Threads, die keine Daemon-Threads sind, wurden gestoppt, entweder durch die Rückkehr von einem Aufruf der Ausführungsmethode oder durch das Auslösen einer Ausnahme, die sich außerhalb der Ausführungsmethode ausbreitet.
Die Art und Weise, Threads zu implementieren, wird in den folgenden Kapiteln vorgestellt
Die Quellcodereferenz lautet wie folgt:
/** * A <i>thread</i> is a thread of execution in a program. The Java * Virtual Machine allows an application to have multiple threads of * execution running concurrently. * <p> * Every thread has a priority. Threads with higher priority are * executed in preference to threads with lower priority. Each thread * may or may not also be marked as a daemon. When code running in * some thread creates a new <code>Thread</code> object, the new * thread has its priority initially set equal to the priority of the * creating thread, and is a daemon thread if and only if the * creating thread is a daemon. * <p> * When a Java Virtual Machine starts up, there is usually a single * non-daemon thread (which typically calls the method named * <code>main</code> of some designated class). The Java Virtual * Machine continues to execute threads until either of the following * occurs: * <ul> * <li>The <code>exit</code> method of class <code>Runtime</code> has been * called and the security manager has permitted the exit operation * to take place. * <li>All threads that are not daemon threads have died, either by * returning from the call to the <code>run</code> method or by * throwing an exception that propagates beyond the <code>run</code> * method. * </ul> * <p> * There are two ways to create a new thread of execution. One is to * declare a class to be a subclass of <code>Thread</code>. This * subclass should override the <code>run</code> method of class * <code>Thread</code>. An instance of the subclass can then be * allocated and started. For example, a thread that computes primes * larger than a stated value could be written as follows: * <hr><blockquote><pre class="brush:php;toolbar:false"> * class PrimeThread extends Thread { * long minPrime; * PrimeThread(long minPrime) { * this.minPrime = minPrime; * } * * public void run() { * // compute primes larger than minPrime * . . . * } * } *
* The following code would then create a thread and start it running: *
** PrimeThread p = new PrimeThread(143); * p.start(); *
* The other way to create a thread is to declare a class that
* implements the Runnable
interface. That class then
* implements the run
method. An instance of the class can
* then be allocated, passed as an argument when creating
* Thread
, and started. The same example in this other
* style looks like the following:
*
* class PrimeRun implements Runnable { * long minPrime; * PrimeRun(long minPrime) { * this.minPrime = minPrime; * } * * public void run() { * // compute primes larger than minPrime * . . . * } * } *
* The following code would then create a thread and start it running: *
** PrimeRun p = new PrimeRun(143); * new Thread(p).start(); *
* Every thread has a name for identification purposes. More than * one thread may have the same name. If a name is not specified when * a thread is created, a new name is generated for it. *
* Unless otherwise noted, passing a {@code null} argument to a constructor * or method in this class will cause a {@link NullPointerException} to be * thrown. * * @author unascribed * @see Runnable * @see Runtime#exit(int) * @see #run() * @see #stop() * @since JDK1.0 */ publicclass Thread implements Runnable {
Bevor Sie einen Thread ausführen, müssen Sie zunächst ein Thread-Objekt erstellen. Beim Erstellen des Thread-Objekts müssen Sie die vom Thread benötigten Attribute angeben, z. B. die Thread-Gruppe, zu der er gehört der Thread gehört, Thread-Priorität und ob es sich um einen Daemon-Thread handelt und andere Informationen. Im neuen Thread wird die folgende Methode aufgerufen, um das Thread-Objekt zu instanziieren. Der Initialisierungscode lautet wie folgt:
/** * Initializes a Thread. * * @param g the Thread group * @param target the object whose run() method gets called * @param name the name of the new Thread * @param stackSize the desired stack size for the new thread, or * zero to indicate that this parameter is to be ignored. * @param acc the AccessControlContext to inherit, or * AccessController.getContext() if null */ private void init(ThreadGroup g, Runnable target, String name, long stackSize, AccessControlContext acc) { if (name == null) { throw new NullPointerException("name cannot be null"); } this.name = name; //当前线程作为该线程的父线程 Thread parent = currentThread(); SecurityManager security = System.getSecurityManager(); //线程组的获取:如果传入的参数为空首先获取系统默认的安全组,如果为空获取父线程的安全组 if (g == null) { /* Determine if it's an applet or not */ /* If there is a security manager, ask the security manager what to do. */ if (security != null) { g = security.getThreadGroup(); } /* If the security doesn't have a strong opinion of the matter use the parent thread group. */ if (g == null) { g = parent.getThreadGroup(); } } /* checkAccess regardless of whether or not threadgroup is explicitly passed in. */ g.checkAccess(); /* * Do we have the required permissions? */ if (security != null) { if (isCCLOverridden(getClass())) { security.checkPermission(SUBCLASS_IMPLEMENTATION_PERMISSION); } } g.addUnstarted(); this.group = g; //设置daemon 、priority 属性为父线程对应的值 this.daemon = parent.isDaemon(); this.priority = parent.getPriority(); if (security == null || isCCLOverridden(parent.getClass())) this.contextClassLoader = parent.getContextClassLoader(); else this.contextClassLoader = parent.contextClassLoader; this.inheritedAccessControlContext = acc != null ? acc : AccessController.getContext(); this.target = target; setPriority(priority); //将父线程的InheritableThreadLocal复制过来 if (parent.inheritableThreadLocals != null) this.inheritableThreadLocals = ThreadLocal.createInheritedMap(parent.inheritableThreadLocals); /* Stash the specified stack size in case the VM cares */ this.stackSize = stackSize; /* Set thread ID */ //生成线程id(一个long型的字段threadSeqNumber) tid = nextThreadID(); }Schlussfolgerung Einem neu erstellten Thread-Objekt (new Thread()) wird von seinem übergeordneten Thread (aktueller Thread) Speicherplatz zugewiesen Der untergeordnete Thread erbt den
Daemon, die Priorität und den contextClassLoader des übergeordneten Threads zum Laden von Ressourcen sowie den vererbbaren ThreadLocal. Gleichzeitig wird dem untergeordneten Thread eine Thread-ID zugewiesen. Ein ausführbares Thread-Objekt schließt seine Initialisierungsarbeit ab und wartet im Heap-Speicher darauf, ausgeführt zu werden.
So erstellen SieThread erbenCode//方法1通过继承Thread实现class MyThread extends Thread{ //需要实现的方法,该方法执行具体的业务逻辑 @Override public void run() { System.out.println(Thread.currentThread().getName() +" @@@@ MyThread。run()我是通过继承Thread实现的多线程"); } }Beschreibung Gefunden durch Thread-Quellcode-Erkennung (Thread implementiert Runnable ) Thread ist eigentlich eine Instanz, die die ausführbare Schnittstelle implementiert, die eine Instanz eines Threads darstellt, und die einzige Möglichkeit, einen Thread zu starten, ist über die start()-Instanzmethode der Thread-Klasse
. Die start()-Methode ist eine native Methode, die einen neuen Thread startet und die run()-Methode ausführt. Es ist sehr einfach, Multithreading auf diese Weise zu implementieren, indem Sie Thread direkt durch Ihre eigene Klasse erweitern und die run()-Methode überschreiben. Sie können einen neuen Thread starten und Ihre eigene definierte run()-Methode ausführen. Der Methodenkörper der run()-Methode stellt die Aufgabe dar, die der Thread abschließen muss, die als
Thread-Ausführungskörperbezeichnet wird. Wenn dieses Thread-Klassenobjekt erstellt wird, wird ein neuer Thread erstellt und tritt in den neuen Thread-Status ein. Durch Aufrufen der start()-Methode, auf die das Thread-Objekt verweist, wechselt der Thread in den Bereitschaftszustand. Zu diesem Zeitpunkt wird der Thread je nach CPU-Planungszeitpunkt möglicherweise nicht sofort ausgeführt. Schnittstelle Runnable implementieren
//方法2通过实现runnable接口 //实现Runnable接口,并重写该接口的run()方法,该run()方法同样是线程执行体,创建Runnable实现类的实例, //并以此实例作为Thread类的target来创建Thread对象,该Thread对象才是真正的线程对象。class MyRunnable implements Runnable{ @Override public void run() { System.out.println(Thread.currentThread().getName()+ " @@@@ MyRunnable。run()我是通过实现Runnable接口实现的多线程"); } }
In Kombination mit der Thread-Pool-Schnittstelle ExecutorService können Sie das legendäre Multithreading mit zurückgegebenen Ergebnissen implementieren . (Die Verwendung von Executor wird in den folgenden Artikeln ausführlich vorgestellt.)
//方法3通过Executor框架实现class MyCallable implements Callable<Integer>{ //需要实现call方法而不是run方法 @Override public Integer call() throws Exception { return 100; } }
Die Quellcodebeschreibung der Startmethode lautet wie folgt:
/** * Causes this thread to begin execution; the Java Virtual Machine * calls the <code>run</code> method of this thread. * <p> * The result is that two threads are running concurrently: the * current thread (which returns from the call to the * <code>start</code> method) and the other thread (which executes its * <code>run</code> method). * <p> * It is never legal to start a thread more than once. * In particular, a thread may not be restarted once it has completed * execution. * * @exception IllegalThreadStateException if the thread was already * started. * @see #run() * @see #stop() */ public synchronized void start() { /** * This method is not invoked for the main method thread or "system" * group threads created/set up by the VM. Any new functionality added * to this method in the future may have to also be added to the VM. * * A zero status value corresponds to state "NEW". */ if (threadStatus != 0) throw new IllegalThreadStateException(); /* Notify the group that this thread is about to be started * so that it can be added to the group's list of threads * and the group's unstarted count can be decremented. */ group.add(this); boolean started = false; try { start0(); started = true; } finally { try { if (!started) { group.threadStartFailed(this); } } catch (Throwable ignore) { /* do nothing. If start0 threw a Throwable then it will be passed up the call stack */ } } } private native void start0();
public class TestCreateThread { public static void main(String[] args) { Thread myThread = new MyThread(); myThread.setName("myThread"); myThread.start(); Runnable myRunnable = new MyRunnable(); Thread myRunnableThread = new Thread(myRunnable); myRunnableThread.setName("myRunnableThread"); myRunnableThread.start(); Thread myRunnableThread2 = new MyThread(myRunnable); myRunnableThread2.setName("myRunnableThread2"); myRunnableThread2.start(); //执行结果参考如下: //myThread @@@@ MyThread。run()我是通过继承Thread实现的多线程 //myRunnableThread2 @@@@ MyThread。run()我是通过继承Thread实现的多线程 //myRunnableThread @@@@ MyRunnable。run()我是通过实现Runnable接口实现的多线程 //测试callable方法 // 创建MyCallable对象 Callable<Integer> myCallable = new MyCallable(); //使用FutureTask来包装MyCallable对象 FutureTask<Integer> ft = new FutureTask<Integer>(myCallable); //FutureTask对象作为Thread对象的target创建新的线程 Thread thread = new Thread(ft); thread.start();//启用 //获取信息 try { //取得新创建的新线程中的call()方法返回的结果 //当子线程此方法还未执行完毕,ft.get()方法会一直阻塞, //直到call()方法执行完毕才能取到返回值。 int sum = ft.get(); System.out.println("sum = " + sum); } catch (InterruptedException e) { e.printStackTrace(); } catch (ExecutionException e) { e.printStackTrace(); } //使用ExecutorService处理多线程 ExecutorService pool = Executors.newFixedThreadPool(10); Future<Integer> f = pool.submit(myCallable); // 关闭线程池 pool.shutdown(); try { int sum1 = f.get(); System.out.println("sum1 = " + sum1); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (ExecutionException e) { e.printStackTrace(); } } }
无论何种方式,启动一个线程,就要给它一个名字!这对排错诊断系统监控有帮助。否则诊断问题时,无法直观知道某个线程的用途。
Thread实现接口Runnable,并且实现了run方法,代码参考如下:
//如果该线程是使用独立的 Runnable 运行对象构造的,则调用该 Runnable 对象的 run 方法; //否则,该方法不执行任何操作并返回。 //Thread 的子类应该重写该方法。 /** * If this thread was constructed using a separate * <code>Runnable</code> run object, then that * <code>Runnable</code> object's <code>run</code> method is called; * otherwise, this method does nothing and returns. * <p> * Subclasses of <code>Thread</code> should override this method. * * @see #start() * @see #stop() * @see #Thread(ThreadGroup, Runnable, String) */ @Override public void run() { if (target != null) { target.run(); } } }
当执行到Thread类中的run()方法时,会首先判断target是否存在,存在则执行target中的run()方法,也就是实现了Runnable接口并重写了run()方法的类中的run()方法。当时如果该Runnable的子类是通过一个继承Thread的子类(该且重写了run方法),则真正执行的是Thread子类重写的run方法(由于多态的原因)。
Das obige ist der detaillierte Inhalt vonDie Verwendung von Java-Parallelitätsthreads und das Erstellen von Startthreads. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!