[JAVA] Programmierung aus einem 51 Jahre alten Memorandum of Thread

Multithread-Zusammenfassung finden Sie hier

Äh

Ich fürchte, also kurz gesagt, ein Memo über die Multithread-Verarbeitung

■ ** Thread ** Klassenerweiterung | ** Runnable ** Schnittstellenvererbung ** Kommunikation mit UI-Thread **   view#post(Runnable)   View#postDelayed(Runnable.long)   runOnUiThread(Runnable) ■ ** AsyncTask ** -Klasse ** Verarbeitung und UI-Thread-Kommunikation ** Mit execute (), doInBackground (), postExecute () usw. ■ ** Handler ** Klasse ** Realisiert die Kommunikation zwischen mehreren Threads (OK, auch wenn es sich nicht um einen UI-Thread handelt) **   Message   Runnable

■Thread(Thread/Runnable) Android läuft auf einem Linux-Prozess mit einem Thread. Dieser Thread wird als einzelner Thread bezeichnet, und MainActivity.java wird in einem einzelnen Thread ausgeführt. Hier wird der Thread, auf dem MainActivity ausgeführt wird, als Hauptthread bezeichnet und beschrieben. Nur der Hauptthread kann UI-Teile direkt verarbeiten. Um UI-Teile von anderen Threads aus zu bedienen, wird eine spezielle Methode verwendet.

MainActivity spielt die Rolle einer vom Benutzer bedienten Schnittstelle. Wenn der Hauptthread also eine zeitaufwändige Verarbeitung durchführt, reagiert der Betriebsbildschirm nicht mehr oder die Gesamtverarbeitung verlangsamt sich, was die Verwendung erschwert. Ich werde am Ende.

Um die Benutzerfreundlichkeit der App zu gewährleisten, müssen Entwurfsprozesse, die nicht mit Benutzervorgängen zusammenhängen, separat über einen separaten Thread (Multithread) verarbeitet werden. Es scheint, dass eine andere Thread-Verarbeitung entweder über die Thread-Klasse oder die Runnable-Schnittstelle erfolgt.

** ** Thread ist eine "öffentliche Klasse Thread erweitert Objekt implementiert Runnable", eine Klasse, die Runnable erbt. Runnable ist "Public Interface Runnable". Wenn Sie die Konstanten und Methoden der Thread-Klasse verwenden möchten, erweitern Sie die Thread-Klasse! Wenn nicht, warum nicht Runnable erben? Bedeutet das?

Da ein anderer Thread ebenfalls auf demselben Linux-Prozess wie der Haupt-Thread verarbeitet wird, sollten Sie bei Problemen mit einem einzelnen Prozess einen anderen Linux-Prozess (Multi-Prozess) starten und bei Bedarf einen weiteren Thread erstellen. Vielleicht (Manifest.java).

□Thread

In einer Unterklasse von Thread


public void onCreate(){
       SubThread subThread = new SubThread();
       subThread.start();
}

class SubThread extends Thread{
      public void run(){
             // todo
      }
}

□Runnable Obwohl es sich um eine Beschreibung von Runnable handelt, gibt es drei bekannte Beschreibungsmethoden.

Anonym funktionsfähig


new Thread(new Runnable(){
    @Override 
    public void run(){
           // todo
    }
}).start();

Verwenden einer Thread-Instanz


public void onCreate(){
       MyRunnable myRunnable = new MyRunnable();
       Thread     thread     = new Thread(myRunnable);
       Thread.start();
}

class MyRunnable implement Runnable{
      @Override 
      public void run(){
             // todo
      }
}

Rufen Sie die Thread-Klasse direkt auf


public void onCreate(){
       Thread thread = new Thread(MyRunnable());
}

class MyRunnable implement Runnable{
      @Override 
      public void run(){
             // todo
      }
}

Thread-Stop-Verarbeitung

  • Thread läuft auf Service
  • Wenn es einen Dienst gibt, wird der Dienst nicht zweimal gestartet.
  • Stopp mit Abbrechen ()

MainActivity.java



@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    //Holen Sie sich die Start- und Stopp-Schaltflächenobjekte!
    Button btn_start = findViewById(R.id.btn_start);
    Button btn_stop  = findViewById(R.id.btn_stop);
    
    final Intent intent = new Intent(this,MyService.class);
    btn_start.setOnClickListener(new View.OnClickListener(){
        @Override
        public void onClick(View view) {
            
            //Wenn MyService nicht gestartet ist, starten Sie es!
            if(!MyService.serviceState) {
                startForegroundService(intent);
            }
        }
    });

    btn_stop.setOnClickListener(new View.OnClickListener(){
        @Override
        public void onClick(View view) {
            // stopService()Also rufe ich onDestroy of MyService ~ an
            stopService(intent);
        }
    });
}

MyService.java



public class MyService extends Service {

    // serviceState =Wenn true, wurde MyService bereits gestartet
    // threadState  =Wenn true, wird Thread weiterhin ausgeführt
    static boolean serviceState;
    boolean threadState;

    public MyService() {
        serviceState = true;
        threadState  = true;
    }

    @Override
    public int onStartCommand(Intent intent,int flags,int startId){

        //Benachrichtigungsinhalt einrichten!
        Notification notification;
        NotificationCompat.Builder builder = new NotificationCompat.Builder(this,"id");
        notification = builder.setSmallIcon(R.drawable.notification_icon)
                              .setContentTitle("sanple")
                              .setContentText("text")
                              .build();

        //Stellen Sie den Benachrichtigungskanal und die Wichtigkeit ein!
        int importance = NotificationManager.IMPORTANCE_LOW;
        NotificationChannel channel = new NotificationChannel("id","name",importance);
        NotificationManager manager = getSystemService(NotificationManager.class);
        manager.createNotificationChannel(channel);
        startForeground(1,notification);

        //Starten Sie den Thread!
        new Thread(new Runnable() {
            @Override
            public void run() {
                int count = 0;

                //Führen Sie das Zählprotokoll alle 2 Sekunden aus, während threadState true ist.
                while(threadState){
                    Log.d("msg",String.valueOf(count));

                    try {
                        sleep(2000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    count++;
                }

            }
        }).start();

        return START_NOT_STICKY;
    }

    @Override
    public void onDestroy(){
        Log.d("msg","onDestroy");

        //StopService in MainActivity()Wenn Sie onDestroy anrufen()Wird genannt
        //MyService wird gestoppt, Thread wird ebenfalls auf gestoppt gesetzt
        serviceState = false;
        threadState  = false;
    }

    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }
}

Thread verwerfen, erzwungene Beendigung

Die Thread-Zerstörung (stop ()) ist in API15 veraltet. Das heißt, schon vorher gab es einen Code-Bedarf, wie zum Beispiel den Wunsch, Thread zu zerstören oder ihn gewaltsam zu beenden, und ich empfahl auch Code, der zerstört werden kann. Es ist jedoch seit API15 veraltet. Dies liegt daran, dass das Verwerfen von Threads viel schlechten Müll hinterlässt.

Wenn Thread normal ausgeführt wird, können geschützte Objekte aufgrund des Verwerfens von Threads instabil werden, was zu unerwartetem Verhalten führen kann. Da es schwierig ist, Objekte zu finden oder zu identifizieren, die von Thread freigegeben wurden, sollten wir uns überlegen, ob Sie ein Programm mit Interrupt () entwerfen können, ohne Thread zu verwerfen, und über API 15 können Sie den Thread zwangsweise beenden. Es wurde veraltet. Verwenden Sie für niedliche niedliche Apps (und für Benutzer, die Ihre App lieben) Thread.stop () nicht, sondern codieren Sie das Design auf Interrupt () Weise!

Wenn du immer noch Stop () magst! Ist es also gut, es so zu verwenden, dass keine Personen (Objekte usw.) vermisst werden?

■ Kommunikation zwischen Threads

□ UI-Thread <-worker-Thread □ Worker-Thread <-Arbeiter-Thread

□ Kommunikation zwischen Threads (Handler: Looper und Queue)

Handle ist eine Klasse, die zwischen Threads kommuniziert, und der Thread, der die Handle-Instanz erstellt hat, verfügt über die für die Kommunikation erforderlichen Funktionen von Queue und Looper. Von anderen Threads gesendete Informationen werden in einer Warteschlange gespeichert, und Looper ruft die gespeicherten Informationen ab und verarbeitet sie im Hauptthread (da sie im Hauptthread verarbeitet werden, ist es auch möglich, UI-Teile zu bedienen).

□ Kommunizieren Sie vom Worker-Thread zum UI-Thread

Es scheint, dass UI-Teile nicht direkt vom Worker-Thread aus bedient werden können. Verwenden Sie daher Methoden und Klassen zum Bedienen von UI-Teilen, um die Operationsverarbeitung von UI-Teilen an den UI-Thread zu übergeben.

  • View.post(Runnable)
  • View.postDelayed(Runnable,long)
  • Activity.runOnUiThread(Runnable)
  • Handler Klasse
  • Asynchrone Verarbeitung der AsyncTask-Klasse

Die Methode zum Bearbeiten von View mit View.post ist schwierig zu warten, da der Vorgang kompliziert wird </ font>. Es gibt auch eine Möglichkeit, Handle im Arbeitsthread zu verwenden, aber AsyncTask wird als Referenz empfohlen.

View.post () und View.postDelayed (), beides Methoden, die in View-Objekten gefunden werden. Post () aus verschiedenen Ansichten (TextView.post () oder Button.Post ()) wird auf der Seite der Empfangswarteschlange als dieselbe View.post () empfangen (identifizieren Sie den Absender als TextView oder EditText). Nicht).

・ View.post ()

public boolean post(Runnable action)

Klassenmethoden anzeigen: Wie TextView.post, TextEdit.post (), Button.post () können Ansichtsteile die Methoden post () und postDelayed () verwenden. post fügt Runnable zur Nachrichtenwarteschlange hinzu und verarbeitet Runnable im UI-Thread. Wenn der ausführbare Prozess erfolgreich ist, wird true zurückgegeben. Wenn false, scheint es viele Fälle zu geben, in denen die Nachrichtenwarteschlange beendet wurde.

Post in Thread-Klasse

activity_main.xml


    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Hello World!"
        android:id="@+id/textView"
        />

Verwenden der Thread-Klasse


public class MainActivity extends AppCompatActivity {

    public static TextView textView;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        textView = (TextView) findViewById(R.id.textView);
        
        //Instantisieren und starten Sie die Thread-Klasse
        ThreadSample threadSample = new ThreadSample();
        threadSample.start();
    }
}

class ThreadSample extends Thread{
    public void run(){
        //Bedienen Sie UI-Teile der Hauptaktivität
        // post()Da die Methode Runnable als Argument verwendet, ist dies wie folgt
        MainActivity.textView.post(new Runnable(){
            @Override
            public void run() {
                MainActivity.textView.setText("From ThreadSample");
            }
        });
    }
}
Post () in anonymer Klasse

Zur Erinnerung, ich werde es auch in der anonymen Klasse schreiben.

python


public class MainActivity extends AppCompatActivity {

    public static TextView textView;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        textView = (TextView) findViewById(R.id.textView);

        new Thread(new Runnable() {
            @Override
            public void run() {
                textView.post(new Runnable() {
                    @Override
                    public void run() {
                        textView.setText("From Another Thread");
                    }
                });
            }
        }).start();
    }
}

・ View.postDelayed

public boolean postDelayed(Runnable action,long delayMillis) Verzögerung ... Verzögerung; Millis ... Millisekunde </ font> postDelayed fügt Runnable zur Nachrichtenwarteschlange hinzu und verarbeitet nach einer bestimmten Zeit die Runnable im UI-Thread.

Wenn Sie den folgenden Code ausführen, wird die Textansicht mit dem Anfangswert "Hello World!" Begrüßt. Nach 5 Sekunden ändert sich die Anzeige jedoch in "From ThreadSample".

activity_main.xml


    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Hello World!"
        android:id="@+id/textView"
        />

In der Thread-Klasse


public class MainActivity extends AppCompatActivity {

    public static TextView textView;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        textView = (TextView) findViewById(R.id.textView);
        ThreadSample threadSample = new ThreadSample();
        threadSample.start();
    }
}

class ThreadSample extends Thread{
    public void run(){
        MainActivity.textView.postDelayed(new Runnable(){
            @Override
            public void run() {
                MainActivity.textView.setText("From ThreadSample");
            }
        },5000);
    }
}

・ Activity.runOnUiThread

public final void runOnUiThread(Runnable action)

Aktivitätsklassenmethode: ** Aktivität kann runOnUiThread () ** verwenden. Aktivität bietet den UI-Bildschirm.

runOnUiThread führt die angegebene Aktion im UI-Thread aus. Wenn der aktuelle Thread ein UI-Thread ist, erfolgt die Aktion sofort! Andernfalls wird die Aktion zur Ereigniswarteschlange des UI-Threads hinzugefügt. Es scheint, dass das Verhalten fast genauso funktioniert wie die post () -Methode! ..

public class MainActivity extends AppCompatActivity {

    public static TextView textView;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        textView = (TextView) findViewById(R.id.textView);

        new Thread(new Runnable(){
            @Override
            public void run() {
                MainActivity.this.runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        textView.setText("runOnUiThread");
                    }
                });
            }
        }).start();
    }
}

■Handler Weitere Informationen finden Sie hier "Hanler Summary" Mit dem Handler können Sie ausführbare Objekte senden und Nachrichten verarbeiten, die der Nachrichtenwarteschlange eines Threads zugeordnet sind. Eine Instanz von Handler ist einem einzelnen Thread und einer Nachrichtenwarteschlange zugeordnet. Gibt true zurück, wenn es zur Nachrichtenwarteschlange hinzugefügt wird. Es ist nicht so, ob der Prozess erfolgreich war. Wenn der Looper vor Ablauf der angegebenen Zeit beendet wird, wird Runnable abgebrochen. Wenn falsch, vermuten Sie, dass die Nachrichtenwarteschlange beendet wurde!

■android.os.AsyncTask public abstract class AsyncTask extends Object android.os.AsyncTask<Params,Progress,Result>

Zusammenfassung hier Referenzcode hier

AsyncTask ist ein asynchroner Prozess. Besonders geeignet für die kurzzeitige asynchrone Verarbeitung. ** Bitte verwenden Sie andere APIs (Executor, ThreadPoolExecutor usw.) ** für die Verarbeitung, die lange läuft!

Recommended Posts