精华内容
下载资源
问答
  • Java线程通信方式

    2016-10-26 19:49:32
    1 wait()、notify()、notifyAll() ...当前线程在拥有一个对象的锁的时候,调用这个对象的wait方法会使当前线程释放对象锁并进入等待状态,wait(n), 参数 0 时无限长 , 负数会抛 java.lang.Ill

    1 wait()、notify()、notifyAll()

    wait()、notify()和notifyAll()是Object类中的本地方法,并且被final修饰,无法被重写,一般在synchronized代码块中使用。当前线程在拥有一个对象的锁的时候,调用这个对象的wait方法会使当前线程释放对象锁并进入等待状态,wait(n), 参数 0 时无限长 , 负数会抛 java.lang.IllegalArgumentException 异常 ,等待 n 毫秒,一旦时间到了 , 就自动进入就绪队列。调用这个对象的notify()方法能够唤醒一个正在等待这个对象的锁的线程,如果有多个线程都在等待这个对象的锁,只能唤醒其中一个线程,调用notifyAll()方法能够唤醒所有正在等待这个对象锁的线程。并且一个线程被唤醒不代表立即获取了对象的锁,只有等当前线程调用完notify()或者notifyAll()并退出synchronized块,释放对象锁后,被唤醒的线程才能获得锁执行。

    2 condition接口

    Condition接口中主要有await()、signal()、signalAll()几个方法,对应Object中的wait()、notify()和notifyAll(),并且condition一般配合lock使用,调用Condition的await()、signal()、signalAll方法,都必须在lock保护之内,就是说必须在lock.lock()和lock.unlock之间才可以使用,可以用lock.newCondition() 生成一个condition对象。在获取对象锁之后可以调用condition的await()方法使当前线程释放对象锁,并进入等待状态,调用signal()方法会唤醒一个正在等待这个对象的锁的线程,调用notifyAll()方法能够唤醒所有正在等待这个对象锁的线程。

    参考链接:http://www.cnblogs.com/dolphin0520/p/3920385.html

    注意:面试可能考查生产者消费者模型

    展开全文
  • 本文总结我对于JAVA线程线程之间的通信方式的理解,主要以代码结合文字的方式来讨论线程间的通信,故摘抄了书中的一些示例代码。 二,线程间的通信方式 ①同步 这里讲的同步是指多个线程通过synchronized...

    多线程和并发,在平时开发中有些小伙伴用的不多,但是有些工作经验的面试中还是容易被问到的,故在之后几期先整理一些常见的多线程面试题供参考。

    通信方式

    • ①同步

    • ②while轮询的方式

    • ③wait/notify机制

    • ④管道通信

    一,介绍

    本文总结我对于JAVA多线程中线程之间的通信方式的理解,主要以代码结合文字的方式来讨论线程间的通信,故摘抄了书中的一些示例代码。

    二,线程间的通信方式

    ①同步

    这里讲的同步是指多个线程通过synchronized关键字这种方式来实现线程间的通信。

    参考示例:

    
     

    public class MyObject {

        synchronized public void methodA() {
            //do something....
        }

        synchronized public void methodB() {
            //do some other thing
        }
    }

    public class ThreadA extends Thread {

        private MyObject object;
    //省略构造方法
        @Override
        public void run() {
            super.run();
            object.methodA();
        }
    }

    public class ThreadB extends Thread {

        private MyObject object;
    //省略构造方法
        @Override
        public void run() {
            super.run();
            object.methodB();
        }
    }

    public class Run {
        public static void main(String[] args) {
            MyObject object = new MyObject();

            //线程A与线程B 持有的是同一个对象:object
            ThreadA a = new ThreadA(object);
            ThreadB b = new ThreadB(object);
            a.start();
            b.start();
        }
    }

    由于线程A和线程B持有同一个MyObject类的对象object,尽管这两个线程需要调用不同的方法,但是它们是同步执行的,比如:线程B需要等待线程A执行完了methodA()方法之后,它才能执行methodB()方法。这样,线程A和线程B就实现了 通信。

    这种方式,本质上就是“共享内存”式的通信。多个线程需要访问同一个共享变量,谁拿到了锁(获得了访问权限),谁就可以执行。

    ②while轮询的方式

    代码如下:

    
     

    import java.util.ArrayList;
    import java.util.List;

    public class MyList {

        private List<String> list = new ArrayList<String>();
        public void add() {
            list.add("elements");
        }
        public int size() {
            return list.size();
        }
    }

    import mylist.MyList;

    public class ThreadA extends Thread {

        private MyList list;

        public ThreadA(MyList list) {
            super();
            this.list = list;
        }

        @Override
        public void run() {
            try {
                for (int i = 0; i < 10; i++) {
                    list.add();
                    System.out.println("添加了" + (i + 1) + "个元素");
                    Thread.sleep(1000);
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    import mylist.MyList;

    public class ThreadB extends Thread {

        private MyList list;

        public ThreadB(MyList list) {
            super();
            this.list = list;
        }

        @Override
        public void run() {
            try {
                while (true) {
                    if (list.size() == 5) {
                        System.out.println("==5, 线程b准备退出了");
                        throw new InterruptedException();
                    }
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    import mylist.MyList;
    import extthread.ThreadA;
    import extthread.ThreadB;

    public class Test {

        public static void main(String[] args) {
            MyList service = new MyList();

            ThreadA a = new ThreadA(service);
            a.setName("A");
            a.start();

            ThreadB b = new ThreadB(service);
            b.setName("B");
            b.start();
        }
    }

    在这种方式下,线程A不断地改变条件,线程ThreadB不停地通过while语句检测这个条件(list.size()==5)是否成立 ,从而实现了线程间的通信。但是这种方式会浪费CPU资源。

    之所以说它浪费资源,是因为JVM调度器将CPU交给线程B执行时,它没做啥“有用”的工作,只是在不断地测试 某个条件是否成立。就类似于现实生活中,某个人一直看着手机屏幕是否有电话来了,而不是:在干别的事情,当有电话来时,响铃通知TA电话来了。

    这种方式还存在另外一个问题:

    轮询的条件的可见性问题,这里不展开了。

    线程都是先把变量读取到本地线程栈空间,然后再去再去修改的本地变量。因此,如果线程B每次都在取本地的 条件变量,那么尽管另外一个线程已经改变了轮询的条件,它也察觉不到,这样也会造成死循环。

    ③wait/notify机制

    代码如下:

    
     

    import java.util.ArrayList;
    import java.util.List;

    public class MyList {

        private static List<String> list = new ArrayList<String>();

        public static void add() {
            list.add("anyString");
        }

        public static int size() {
            return list.size();
        }
    }


    public class ThreadA extends Thread {

        private Object lock;

        public ThreadA(Object lock) {
            super();
            this.lock = lock;
        }

        @Override
        public void run() {
            try {
                synchronized (lock) {
                    if (MyList.size() != 5) {
                        System.out.println("wait begin "
                                + System.currentTimeMillis());
                        lock.wait();
                        System.out.println("wait end  "
                                + System.currentTimeMillis());
                    }
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }


    public class ThreadB extends Thread {
        private Object lock;

        public ThreadB(Object lock) {
            super();
            this.lock = lock;
        }

        @Override
        public void run() {
            try {
                synchronized (lock) {
                    for (int i = 0; i < 10; i++) {
                        MyList.add();
                        if (MyList.size() == 5) {
                            lock.notify();
                            System.out.println("已经发出了通知");
                        }
                        System.out.println("添加了" + (i + 1) + "个元素!");
                        Thread.sleep(1000);
                    }
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    public class Run {

        public static void main(String[] args) {

            try {
                Object lock = new Object();

                ThreadA a = new ThreadA(lock);
                a.start();

                Thread.sleep(50);

                ThreadB b = new ThreadB(lock);
                b.start();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    线程A要等待某个条件满足时(list.size()==5),才执行操作。线程B则向list中添加元素,改变list 的size。

    A,B之间如何通信的呢?也就是说,线程A如何知道 list.size() 已经为5了呢?

    这里用到了Object类的 wait() 和 notify() 方法。

    当条件未满足时(list.size() !=5),线程A调用wait() 放弃CPU,并进入阻塞状态。---不像②while轮询那样占用CPU

    当条件满足时,线程B调用 notify()通知 线程A,所谓通知线程A,就是唤醒线程A,并让它进入可运行状态。

    这种方式的一个好处就是CPU的利用率提高了。

    但是也有一些缺点:比如,线程B先执行,一下子添加了5个元素并调用了notify()发送了通知,而此时线程A还执行;当线程A执行并调用wait()时,那它永远就不可能被唤醒了。因为,线程B已经发了通知了,以后不再发通知了。这说明:通知过早,会打乱程序的执行逻辑。

    ④管道通信

    就是使用java.io.PipedInputStream 和 java.io.PipedOutputStream进行通信

    具体就不介绍了。分布式系统中说的两种通信机制:共享内存机制和消息通信机制。感觉前面的①中的synchronized关键字和②中的while轮询 “属于” 共享内存机制,由于是轮询的条件使用了volatile关键字修饰时,这就表示它们通过判断这个“共享的条件变量“是否改变了,来实现进程间的交流。

    而管道通信,更像消息传递机制,也就是说:通过管道,将一个线程中的消息发送给另一个。

    展开全文
  • 掌握Android的多线程通信机制,我们首先应该掌握Android中进程与线程是什么。###1. 进程在Android中,一个应用程序就是一个独立的进程(应用运行在一个独立的环境中,可以避免其他应用程序/进程的干扰)。一般来说,当...

    掌握Android的多线程通信机制,我们首先应该掌握Android中进程与线程是什么。

    ###1. 进程

    在Android中,一个应用程序就是一个独立的进程(应用运行在一个独立的环境中,可以避免其他应用程序/进程的干扰)。一般来说,当我们启动一个应用程序时,系统会创建一个进程(从Zygote中fork出来的,这个进程会有独立的ID),并为这个进程创建一个主线程(UI线程),然后就可以运行MainActivity了,应用程序的组件默认都是运行在它的进程中,但我们可以通过指定应用的组件(四大组件)的运行进程:`android:process`来让组件运行在不同的进程中;让组件运行在不同的进程中,会带来好处,也会带来坏处:

    好处是:因为每一个应用程序(也就是每一个进程)都会有一个内存预算,所有运行在这个这个进程中的程序使用的总内存不能超过这个值,让组件运行不同的进程中,可以让主进程可以拥有更多的空间资源。

    坏处是:每个进程都会有自己的虚拟机实例,因此让在进程间共享一些数据变得困难;(当然,我们可以采用多进程间的通信来实现数据的共享)

    当我们的应用程序比较大,需要的内存资源比较多时(也就是用户会抱怨应用经常出现OutOfMemory时),可以考虑使用多进程

    2. 线程

    在Java中,线程会有那么几种状态:创建,就绪,运行,阻塞,死亡。当应用程序有组件在运行时,UI线程是处于运行状态的。默认情况下,应用的所有组件的操作都是在UI线程里完成的,包括响应用户的操作(触摸,点击等),组件生命周期方法的调用,UI的更新等。因此如果UI线程处理阻塞状态时(在线程里做一些耗时的操作,如网络连接等),就会不能响应各种操作,如果阻塞时间达到5秒,就会让程序处于ANR(application not response)状态,这时用户就可能退出你的应用甚至卸载你的应用,这是我们不能接受的。 这时,有人就会说,我们在其他线程中更新UI不就可以了吗,就不会导致UI线程处于阻塞状态了。但答案是否定的。

    因为Android的UI线程是非线程安全的,应用更新UI,是调用invalidate()方法来实现界面的重绘,而invalidate()方法是非线程安全的,也就是说当我们在非UI线程来更新UI时,可能会有其他的线程或UI线程也在更新UI,这就会导致界面更新的不同步。因此我们不能在非UI主线程中做更新UI的操作。也就是说我们在使用Android中的线程时,要保证:

    不能阻塞UI主线程,也就是不能在UI主线程中做耗时的操作,如网络连接,文件的IO;

    只能在UI主线程中做更新UI的操作;

    在Android中,我们把除UI线程外的,其他所有的线程都叫做工作线程,也就是说Android只会存在两种线程:UI主线程(UI thread)和工作线程(work thread).我们不能在UI主线程中做耗时的操作,因此我们可以把耗时的操作放在另一个工作线程中去做。操作完成后,再通知UI主线程做出相应的响应。这就需要掌握线程间通信的方式了。在Android中提供了两种线程间的通信方式:一种是AsyncTask机制,另一种是Handler机制;

    2.1 Android线程间通信方式之AsyncTask机制

    AsyncTask,异步任务,也就是说在UI线程运行的时候,可以在后台的执行一些异步的操作;AsyncTask可以很容易且正确地使用UI线程,AsyncTask允许进行后台操作,并在不显示使用工作线程或Handler机制的情况下,将结果反馈给UI线程。但是AsyncTask只能用于短时间的操作(最多几秒就应该结束的操作),如果需要长时间运行在后台,就不适合使用AsyncTask了,只能去使用Java提供的其他API来实现。

    2.1.1 AsyncTask的使用

    AsyncTask只能通过继承来使用,如:

    private class DownloadFilesTask extends AsyncTask { //处理异步任务的方法,是在工作线程中执行的,必须实现这个方法

    protected Long doInBackground(URL... urls) {

    int count = urls.length;

    long totalSize = 0;

    for (int i = 0; i < count; i++) {

    totalSize += Downloader.downloadFile(urls[i]);

    publishProgress((int) ((i / (float) count) * 100));

    // Escape early if cancel() is called

    if (isCancelled()) break;

    }

    return totalSize;

    }

    //更新后台任务的完成进度,可随时向UI线程反馈执行进度,方法是在UI线程中执行的

    protected void onProgressUpdate(Integer... progress) {

    setProgressPercent(progress[0]);

    }

    //任务的最终结果,这个方法是在UI线程中执行的,

    protected void onPostExecute(Long result) {

    showDialog("Downloaded " + result + " bytes");

    }

    }

    AsyncTask的几个参数,AsyncTask :

    Params..要执行的任务的参数类型;

    Progress,在后台执行的任务的进度;

    Results,后台执行的任务的最后结果;

    当一个AsyncTask任务执行时,它会经历四个步骤:

    1.onPreExecute(),在任务执行前调用,用来做一些UI的初始化工作,在UI线程中执行,如执行一个AsyncTask的下载任务时,初始化类似“正在下载中”的窗口;

    2. doInBackground(Params...),在后台执行任务,是在工作线程中进行的;

    3. onProgressUpdate(Progress...),更新正在后台执行任务的进度,在UI线程中工作,可用来向通知用户任务现在的完成进度(可更新UI),在调用这个方法前,需要在第2个步骤里调用 publishProgress(Progress...)将进度传递给这个方法;

    4. onPostExecute(Result),在后台任务完成后,会将结果返回给这个方法,在UI线程中调用,可以更新UI;

    在使用AsyncTask的时候,需要注意的地方:

    AsyncTask类必须在UI线程中加载,这在在Android Jelly_Bean版本后这些都是自动完成的;

    AsyncTask类必须在UI线程中实例化;

    不要手动去调用onPreExecute(),doInBackground(Params...),publishProgress(Progress...),onPostExecute(Result)方法,这些方法都会由系统自动去调用。

    execute(Params...)方法必须在UIt线程中调用,如在UI线程中执行这个语句:new DownloadFilesTask().execute(url1, url2, url3);我们不需要做其他的工作,这个下载任务就会自动在后台执行了,并且AsynacTask任务只能执行一次;

    2.2 Android线程间通信方式之Handler机制;

    使用Handler机制,也就是通过使用Handler,Looper,MessageQueue,和Message这几个类协调来完成。我们先来看使用Handler机制完成线程间通信的原理,然后再详细介绍这几个类;先看一下这几个类的作用:

    Handler,发送和处理Message对象和Runnable对象;

    Looper,用于从MessageQueue中取出消息(Message)对象,并发送给Handler处理;

    MessageQueue,消息队列,用于存放通过Handler发布的消息;

    Message,消息的类型,里面包含几个实例对象:

    what,用户定义的int型消息代码,用来描述消息;

    obj,随消息发送的用户用户指定对象;

    target,处理消息的Handler;

    一个Handler对象仅与一个Looper相关联,一个Message也仅与一个目标Handler对象相关联,一个Looper对象拥有一个MessageQueue。但多个不同的Handler对象可以与同一个对象相关联,也就是说多个Handler可以共享一个MessageQueue,从而达到消息共享的目的,这也是Android通过Handler机制实现多线程间通信的核心原理;

    上面说到Handler对象仅与一个Looper相关联,那么这个关联是什么时候实现的呢?答案是:Handler对象创建的时候。UI主线程在创建的时候就会拥有一个handler对象和一个Looper对象(工作线程需要自己调用Looper.prepare()来创建一个Looper对象),然后任何在UI主线程中创建的Handler对象默认都会与UI主线程的Looper对象相关联(Handler对象创建的时候,会与这个线程的Looper对象相关联)。进而我们就可以把在UI主线程中创建的Handler对象传递给(依赖注入或引用形式)工作线程,那么在工作线程中用这个Handler对象处理的消息就是在UI主线程的MessageQueue中处理的,从而达到线程间通信的目的。

    了解了使用Handler机制来实现Android线程间异步通信的原理,下面我们再来详细了解下这四个核心类;

    2.2.1 Handler

    Handler,继承自Object类,用来发送和处理Message对象或Runnable对象;Handler在创建时会与当前所在的线程的Looper对象相关联(如果当前线程的Looper为空或不存在,则会抛出异常,此时需要在线程中主动调用Looper.prepare()来创建一个Looper对象)。使用Handler的主要作用就是在后面的过程中发送和处理Message对象和让其他的线程完成某一个动作(如在工作线程中通过Handler对象发送一个Message对象,让UI线程进行UI的更新,然后UI线程就会在MessageQueue中得到这个Message对象(取出Message对象是由其相关联的Looper对象完成的),并作出相应的响应)。

    Handler用post体系来完成发送Runnable对象的工作,用sendMessage体系 来完成发送Message对象的工作;

    post体系,允许把一个Runnable对象发送到消息队列中,它的方法有:post(Runnable),postDelayed(Runnable,long),postAtTime(Runnable,long);

    sendMessage体系,把Message对象发送给消息队列,它的方法有:sendEmptyMessage(int),sendMessage(Message),sendMessageDelayed(Message,long),sendMessageAtTime(Message,long);

    如果Handler是通过post体系将Runnable对象发送到MessageQueue队列中,则这个Runnable对象的run()方法是运行在Handler对象创建时所在线程;

    如果Handler是通过sendMessage体系将Message发送到MessageQueue中,则需要重写handleMessage()方法来获取工作线程传递过来的Message对象,handleMessage()方法是工作在Handler对象建立时所在的线程的(一般我们会在UI线程中建立Handler对象,然后传递给子线程,此时这个Handler对象的handleMessage()方法就是运行在UI主线程中的);

    2.2.2 Message

    Message用来定义一个包含任意数据的消息对象,这个消息对象是可以被发送给Handler处理的。我们最好通过Message.obtain()和Handler.obtatinMessage()来得到一个Message对象(通过这两个方法得到的对象是从对象回收池中得到,也就是说是复用已经处理完的Message对象,而不是重新生成一个新对象),如果通过Message的构造方法得到一个Message对象,则这个Message对象是重新生成的(不建议使用这种方法)。

    Message对象用来封装需要传递的消息,Message的数据结构为:

    Message{

    int arg1;//如果我们只需要存储一些简单的Integer数据,则可通过设置这个属性来传递

    int agr2;//使用同arg1

    Object obj; //设置需要发送给接收方的对象,这个对象需要实现序列化接口

    int what; //描述这个消息的标识;

    //设置与这个消息对应的任意数据,这个数据是用Bundle封装的;

    void setData(Bundle data);

    Bundle getData(); 得到与这个消息对应的数据信息;

    //省略了方法和可选的属性

    ......

    如果需要通过Message对象传递一些比较复杂的数据,则需要使用将数据封装成Bundle对象,然后通过setData(Bundle)方法来传递,用getData()来得到与这个消息对应的数据(这方法与设置Message的Object 属性作用相同);

    2.2.3 MessageQueue

    MessageQueue保存由Looper调度的消息列表,消息通过与Looper相关联的Handler对象添加进MessageQueue。

    2.2.4 Looper

    Looper为线程运行一个消息的循环队列,主要就是为了完成MessageQueue与Handler交互的功能;需要注意的是线程默认并不会给我们提供一个一个Looper实例来管理消息队列,我们需要在线程中主动调用Looper.prepare()方法来实例化一个Looper对象,用于管理消息队列;Looper对象会不断去判断MessageQueue是否为空,如果不空,则将Message取出给相应的Handler进行处理;如果MessageQueue为空,则Looper对象会进行阻塞状态,直到有新的消息进入MessageQueue;

    展开全文
  • Android中子线程和UI线程之间通信的详细解释1.在多线程编程这块,我们经常要使用Handler,Thread和Runnable这三个类,那么他们之间的关系你是否弄清楚了呢?下面详解一下。2.首先在开发Android应用时必须遵守单线程...

    Android中子线程和UI线程之间通信的详细解释

    1.在多线程编程这块,我们经常要使用Handler,Thread和Runnable这三个类,那么他们之间的关系你是否弄清楚了呢?下面详解一下。

    2.首先在开发Android应用时必须遵守单线程模型的原则:

    Android UI操作并不是线程安全的并且这些操作必须在UI线程中执行。

    3.Handler:

    (1).概念:

    Handler是沟通Activity 与Thread/runnable的桥梁。而Handler是运行在主UI线程中的,它与子线程可以通过Message对象来传递数据。

    (2).使用:

    A:Handler是运行在UI线程中,主要接收子线程发送的数据信息, 并用此数据配合主线程更新UI,用来跟UI主线程交互用。比如可以用handler发送一个message,然后在handler的线程中来接收、处理该消息。

    B:消息的处理者。通过Handler对象我们可以封装Message对象,然后通过sendMessage(msg)把Message对象添加到MessageQueue中;当MessageQueue循环到该Message时,就会调用该Message对象对应的handler对象的handleMessage()方法对其进行处理。

    C:Handler可以分发Runnable对象,也可以分发Message对象。

    4.Message:

    消息对象,顾名思义就是记录消息信息的类。也就是说是信息的载体,存放信息内容。这个类有几个比较重要的字段:

    (1).arg1和arg2:我们可以使用两个字段用来存放我们需要传递的整型值,在Service中,我们可以用来存放Service的ID。

    (2).obj:该字段是Object类型,我们可以让该字段传递某个对象到消息的接受者中。

    (3).what:这个字段可以说是消息的标志,判断是接收了哪个消息。在消息处理中,我们可以根据这个字段的不同的值进行不同的处理,类似于我们在处理Button事件时,通过switch(v.getId())判断是点击了哪个按钮。

    Android推荐通过Message.obtain()或者Handler.obtainMessage()获取Message对象。这并不一定是直接创建一个新的实例,而是先从消息池中看有没有可用的Message实例,存在则直接取出并返回这个实例。反之如果消息池中没有可用的Message实例,则根据给定的参数new一个新Message对象。通过分析源码可得知,Android系统默认情况下在消息池中实例化10个Message对象。

    5.源码展示:

    (1).activity_main.xml布局文件:

    xmlns:tools="http://schemas.android.com/tools"

    android:id="@+id/container"

    android:layout_width="match_parent"

    android:layout_height="match_parent"

    android:orientation="vertical" >

    android:id="@+id/btn"

    android:layout_width="wrap_content"

    android:layout_height="wrap_content"

    android:text="自定义Thread继承Thread" />

    android:id="@+id/btn2"

    android:layout_width="wrap_content"

    android:layout_height="wrap_content"

    android:text="自定义Runnable实现Runnable" />

    android:id="@+id/btn3"

    android:layout_width="wrap_content"

    android:layout_height="wrap_content"

    android:text="定时更新UI界面,Handler分发Runnable对象" />

    android:id="@+id/btn4"

    android:layout_width="wrap_content"

    android:layout_height="wrap_content"

    android:text="定时更新UI界面,Handler分发Message对象" />

    android:id="@+id/tv"

    android:layout_width="wrap_content"

    android:layout_height="wrap_content"

    android:text="0" />

    (2).MainActivity.java

    package com.chengdong.su.threaddemo;

    import com.chengdong.su.threaddemo.util.MyRunnable;

    import com.chengdong.su.threaddemo.util.MyThread;

    import android.R.integer;

    import android.app.Activity;

    import android.os.Bundle;

    import android.os.Handler;

    import android.os.Message;

    import android.util.Log;

    import android.view.View;

    import android.view.View.OnClickListener;

    import android.widget.Button;

    import android.widget.TextView;

    public class MainActivity extends Activity implements OnClickListener {

    /** TAG */

    private final String TAG = getClass().getSimpleName();

    /** the object of the button */

    private Button mButton;

    /** the object of the button */

    private Button mButton2;

    /** the object of the button */

    private Button mButton3;

    /** the object of the button */

    private Button mButton4;

    /** the object of the TextView */

    private TextView mTextView;

    /** 计数 */

    private int mCount = 0;

    /** 标志 */

    private int MESSAGE_FLAG = 1;

    /**

    * Handler分发Runnable对象的方式

    */

    private Handler mHandler = new Handler();

    Runnable runnable = new Runnable() {

    @Override

    public void run() {

    mCount++;

    mHandler.postDelayed(runnable, 1000);

    mTextView.setText(mCount + "");

    }

    };

    /***

    * Handler分发Message对象的方式

    */

    Handler mHandler2 = new Handler() {

    public void handleMessage(android.os.Message msg) {

    if (msg.what == 1) {

    mTextView.setText("Handler分发Message对象的方式");

    }

    }

    };

    @Override

    protected void onCreate(Bundle savedInstanceState) {

    super.onCreate(savedInstanceState);

    setContentView(R.layout.activity_main);

    initView();

    }

    /**

    * 初始化组件对象

    */

    private void initView() {

    mButton = (Button) findViewById(R.id.btn);

    mButton2 = (Button) findViewById(R.id.btn2);

    mButton3 = (Button) findViewById(R.id.btn3);

    mButton4 = (Button) findViewById(R.id.btn4);

    mButton.setOnClickListener(this);

    mButton2.setOnClickListener(this);

    mButton3.setOnClickListener(this);

    mButton4.setOnClickListener(this);

    mTextView = (TextView) findViewById(R.id.tv);

    }

    @Override

    public void onClick(View v) {

    switch (v.getId()) {

    case R.id.btn: {

    // 方法一:继承的方式:自定义Thread继承Thread,开启一个新的线程

    new MyThread().start();

    break;

    }

    case R.id.btn2: {

    // 方法二:实现的方式:implement Runnable

    new Thread(new MyRunnable()).start();

    break;

    }

    // 方法三:handler分发Runnable对象:定时更新UI界面 提交计划任务马上执行

    case R.id.btn3: {

    // Handler分发Runnable对象

    mHandler.post(runnable);

    break;

    }

    // 方法四:Handler分发Message对象 ,定时更新UI界面 提交计划任务马上执行

    case R.id.btn4: {

    // 不推荐这种方式

    // Message msg = new Message();

    // 推荐使用这种获取对象的方式:从消息池中获得可用的Message对象

    Message msg = Message.obtain();

    msg.what = MESSAGE_FLAG;

    mHandler2.sendMessage(msg);

    break;

    }

    default:

    break;

    }

    }

    }

    (3).MyRunnable.java

    package com.chengdong.su.threaddemo.util;

    import android.util.Log;

    /***

    * 自定义一个MyRunnable线程

    *

    * @author scd

    *

    */

    public class MyRunnable implements Runnable {

    public MyRunnable() {

    super();

    }

    /** TAG */

    private final String TAG = getClass().getSimpleName();

    @Override

    public void run() {

    for (int i = 0; i < 20; i++) {

    Log.e(TAG, Thread.currentThread().getName() + ",实现的方法" + i);

    }

    }

    }

    (4)MyThread.java

    package com.chengdong.su.threaddemo.util;

    import android.util.Log;

    /***

    * 自定义一个线程

    *

    * @author scd

    *

    */

    public class MyThread extends Thread {

    public MyThread() {

    super();

    }

    /** TAG */

    private final String TAG = getClass().getSimpleName();

    @Override

    public void run() {

    super.run();

    for (int i = 0; i < 10; i++) {

    Log.e(TAG, Thread.currentThread().getName() + ",继承Thread类:" + i);

    }

    }

    }

    展开全文
  • 决定了在UI线程中不能进行耗时任务,在开发过程中,需要将网络、io等耗时任务放在工作线程中执行,工作线程中执行完成后需要在UI线程中进行刷新,因此就有了Handler进程内线程通信机制,当然Handler并不是只能用在UI...
  • 前言多线程的应用在Android开发中是非常常见的,常用方法主要有:今天,我将献上一份全面 ... Android多线程实现方式Android多线程实现方式包括:下面我会对每一个Android多线程实现方式进行详细说明。3. 基础使用An...
  • Java线程间通信的方式线程间的通信方式①同步这里讲的同步是指多个线程通过 synchronized 关键字这种方式来实现线程间的通信。参考示例:[](javascript:void(0)????public class MyObject {synchronized public void...
  • 一,介绍本总结我对于JAVA线程线程之间的通信方式的理解,主要以代码结合文字的方式来讨论线程间的通信,故摘抄了书中的一些示例代码。二,线程间的通信方式①同步这里讲的同步是指多个线程通过synchronized...
  • 可以通过以下几种方式实现:等待通知机制等待通知模式是 Java 中比较经典的线程通信方式。两个线程通过对同一对象调用等待 wait() 和通知 notify() 方法来进行通讯。如两个线程交替打印奇偶数:public class ...
  • java线程通信方式

    2018-10-21 14:25:50
    java线程通信方式 https://www.cnblogs.com/hapjin/p/5492619.html
  • Java线程通信下一节>上述例题无条件的阻塞了其他线程异步访问某个方法。Java对象中隐式管程的应用是很强大的,但是你可以通过进程间通信达到更微妙的境界。这在Java中是尤为简单的。像前面所讨论过的,多线程...
  • 命令式编程中线程通信...Java 并发采用共享内存模型,线程之间的通信总是隐式进行,整个通信过程对程序员完全透明。volatile 告知程序任何对变量的读需要从主内存中获取,写必须同步刷新回主内存,保证所有线程对...
  • Java线程通信-回调的实现方式Java线程通信是非常复杂的问题的。线程间通信问题本质上是如何将与线程相关的变量或者对象传递给别的线程,从而实现交互。比如举一个简单例子,有一个多线程的类,用来计算文件的MD5...
  • 本文将讲解以下几个JAVA线程通信的主题:1、通过共享对象通信线程间发送信号的一个简单方式是在共享对象的变量里设置信号值。线程A在一个同步块里设置boolean型成员变量hasDataToProcess为true,线程B也在同步块里...
  • Java线程通信方式volatile等待/通知机制join方式threadLocalvolatile关键字方式volatile有两大特性,一是可见性,二是有序性,禁止指令重排序,其中可见性就是可以让线程之间进行通信。volatile语义保...
  • 但是当我们需要多个线程之间相互协作的时候,就需要我们掌握Java线程通信方式。本文将介绍Java线程之间的几种通信原理。5.1 锁与同步在Java中,锁的概念都是基于对象的,所以我们又经常称它为对象锁。线程和锁的...
  • 一,介绍本总结我对于JAVA线程线程之间的通信方式的理解,主要以代码结合文字的方式来讨论线程间的通信,故摘抄了书中的一些示例代码。二,线程间的通信方式①同步这里讲的同步是指多个线程通过synchronized...
  • Java线程通信

    2020-09-12 22:59:17
    线程通信是Java线程部分的重点,我们介绍一下常见的几种线程通信方式。 线程锁与同步 锁机制是线程通信的一种重要方式。当多个线程竞争某一个对象时,一旦某个线程获得对象就会立刻将其上锁,其他线程只能等待锁被...
  • 5种方式为:synchronized加wait/notify方式、ReentrantLock加Condition方式、闭锁的方式、栅栏的方式、信号量的方式。最后还介绍了join和yield的使用。1、synchronized加wait/notify方式/*** wait和notify的使用* ...
  • DelayQueue:延迟队列,注入其中的元素必须实现 java.util.concurrent.Delayed 接口 所有BlockingQueue的使用方式类似,以下例子一个线程写入,一个线程读取,操作的是同一个Queue: public class ...
  • 一,介绍本总结我对于JAVA线程线程之间的通信方式的理解,主要以代码结合文字的方式来讨论线程间的通信,故摘抄了书中的一些示例代码。二,线程间的通信方式①同步这里讲的同步是指多个线程通过synchronized...
  • 等待通知模式是 Java 中比较经典的线程通信方式。 两个线程通过对同一对象调用等待 wait() 和通知 notify() 方法来进行通讯。 如两个线程交替打印奇偶数: public class TwoThreadWaitNotify { private int...
  • 1.线程通信 经典例题:生产者/消费者问题 public class Counter { int num = 0; //生产者生产 public synchronized void add(){ if(num == 0){ try { Thread.sleep(1000); } catch (InterruptedException e)...
  • 但是当我们需要多个线程之间相互协作的时候,就需要我们掌握Java线程通信方式。本文将介绍Java线程之间的几种通信原理。5.1 锁与同步在Java中,锁的概念都是基于对象的,所以我们又经常称它为对象锁。线程和锁的...
  • 1.1 基本概念以及线程与进程之间的区别联系关于进程和线程,首先从定义上理解就有所不同:进程是具有一定独立功能的程序、它是系统进行资源分配和调度的一个独立单位,重点在系统调度和单独的单位,也就是说进程是...
  • 一,介绍本总结我对于JAVA线程线程之间的通信方式的理解,主要以代码结合文字的方式来讨论线程间的通信,故摘抄了书中的一些示例代码。二,线程间的通信方式①同步这里讲的同步是指多个线程通过synchronized...
  • 1. 同步这里讲的同步是指多个线程通过synchronized关键字这种方式来实现线程间的通信。public class MyObject {synchronized public void methodA() {//do something....}synchronized public void methodB() {//do ...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 2,888
精华内容 1,155
关键字:

java线程通信方式

java 订阅