Runnable和Thread基础

线程的创建方式有两种:

implements Runnable和extends Thread。

继承Thread类:

package com.test.threadtest;

import android.os.Bundle;
import android.app.Activity;
import android.view.Menu;

public class MainActivity extends Activity {

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

        mThread thread = new mThread();//创建线程
        thread.start();//启动线程
    }

    class mThread extends Thread{
        @Override
        public void run() {

        }
    }
}

这里当调用start()方法的时候就会,线程就会进入线程队列中,一旦线程获取到了CPU的时间片,线程就会执行run()方法。当run()方法执行完毕,线程就会被销毁。

实现Runnable接口:

package com.test.threadtest;

import android.os.Bundle;
import android.app.Activity;
import android.view.Menu;

public class MainActivity extends Activity {

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

        mThread mthread = new mThread();
        Thread thread = new Thread(mthread);//创建线程
        thread.start();//启动线程
    }

    class mThread implements Runnable{

        @Override
        public void run() {

        }

    }
}

两种方式的比较:

(1)Runnable方式可以避免Thread方式由于Java单继承特性带来的缺陷。
(2)Runnable的代码可以被多个线程(Thread实例)共享,适合于多个线程处理同一资源的情况。
第二不同之处的解释:

用实现Runnable接口的方式:

package com.test.threadtest;

import android.os.Bundle;
import android.app.Activity;
import android.view.Menu;

public class MainActivity extends Activity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        //创建三个线程来模拟三个售票窗口
        mThread mthread = new mThread();
        Thread thread1 = new Thread(mthread,"窗口一");//创建线程
        Thread thread2 = new Thread(mthread,"窗口二");//创建线程
        Thread thread3 = new Thread(mthread,"窗口三");//创建线程

        thread1.start();//启动线程
        thread2.start();//启动线程
        thread3.start();//启动线程
    }

    class mThread implements Runnable{
        private int ticketsCount = 5;//总共有5张票


        @Override
        public void run() {
            while(ticketsCount>0){
                ticketsCount--;
                //Thread.currentThread():获取当前的线程
                System.out.println(Thread.currentThread().getName()+"卖了一张票,剩余票数为:"+ticketsCount);
            }
        }

    }
}

结果截图:
这里写图片描述

用继承Thread类的方式:

package com.test.threadtest;

import android.os.Bundle;
import android.app.Activity;
import android.view.Menu;

public class SecondActivity extends Activity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        //创建三个线程模拟三个窗口卖票
        mThread mthread1 = new mThread("窗口一");
        mthread1.start();
        mThread mthread2 = new mThread("窗口二");
        mthread2.start();
        mThread mthread3 = new mThread("窗口三");
        mthread3.start();
    }

    class mThread extends Thread{
        private int ticketsCont = 5;//一共有5张火车票
        private String name;//窗口,也就是线程的名字

        public mThread(String name) {
            this.name = name;
        }

        @Override
        public void run() {
            while(ticketsCont>0){
                ticketsCont--;
                System.out.println(name+"卖了一张票,剩余票数为:"+ticketsCont);
            }

        }

    }
}

结果截图:
这里写图片描述

造成这种结果差异的原因分析:
实现Runnable接口的代码中,创建的三个线程中传递的是同一个Runnable对象,所引用的是同一个资源对象。
继承Thread类的代码中,创建的三个线程对象,每个线程对象中的资源也是独立的,并不是共享的。

线程的生命周期:

这里写图片描述

从图中可以看出线程的一生中一共有5种状态,分别是:
(1)新建状态: 也就是new出一个线程对象,新建一个线程对象,如:Thread thread = new Thread();
(2)就绪状态: 创建了线程对象后,调用了线程的start()方法,此时线程只是进入了线程队列,等待获取CPU服务,具备了运行条件,但并不一定已经开始运行了。
因为这个时候CPU有可能正在执行其他的线程,而我们当前的这个线程可能要等待,当获取到了CPU服务才会进入运行状态。
(3)运行状态: 处于就绪状态的线程,一旦获取了CPU资源,便进入到运行状态,开始执行run()方法里面的逻辑。
(4)终止状态: 线程的run()方法执行完毕,或者线程调用了stop()方法,线程便进入终止状态。
(5)阻塞状态: 一个正在run()方法中执行的线程在某些情况下,由于某种原因而暂时让出了CPU资源,暂停了自己的执行,便进入了阻塞状态,如调用了sleep()方法。
也就是说,如果在run()方法中调用sleep()方法,就会休眠自己进入阻塞状态,也就会把自己所占用的CPU资源让出来,让其他线程去获取CPU资源,当休眠时间过了之后,线程就会解除阻塞状态进入就绪状态,等待获取CPU资源。

守护线程:

Java中线程有两类:
(1)用户线程:运行在前台,执行具体的任务。
如:程序的主线程,连接网络的子线程等都是用户线程
(2)守护线程:运行在后台,为其他前台的用户线程服务。
特点:
一旦所有用户线程都结束运行,守护线程会随JVM虚拟机一起结束工作。
应用:
数据库连接池中的检测线程,JVM虚拟机启动后的监测线程
最常见的守护线程:垃圾回收线程
将线程设置为守护线程的方法:
可以通过调用Thread类的setDaemon(true)方法来设置当前的线程为守护线程。
使用守护线程的注意事项:
1.setDaemon(true)必须在start()方法之前调用,否则会抛出IllegalThreadStateException异常。
2.在守护线程中产生的新线程也是守护线程。
3.不是所有的任务都可以分配给守护线程来执行,比如读写操作或者计算逻辑。原因是:当我们在守护线程中执行着读写操作,当读写操作执行到一半的时候,所有的用户线程都退出来了,那么守护线程就会随JVM虚拟机一起结束工作,然而读写操作还没进行完所以程序就崩溃了。
下面用一个例子解释主线程与守护线程之间的关系:(守护线程在某一个时间内不停的往一个文件中写数据,主线程则阻塞等待键盘的输入,一旦主线程获得了用户的输入阻塞就会解除,主线程继续运行直到结束,而一旦主线程结束守护线程就会销毁,但是守护线程中的写入操作不一定就执行完毕了)

源码:

package com.test.test;

import java.io.File;
import java.io.FileOutputStream;
import java.io.OutputStream;
import java.util.Scanner;

public class Test {

    public static void main(String[] args) {
        System.out.println("进入了主线程"+Thread.currentThread().getName());
        DaemonThread daemonThread = new DaemonThread();
        Thread thread  = new Thread(daemonThread);
        thread.setDaemon(true);//设置为守护线程
        thread.start();

        Scanner sc = new Scanner(System.in);
        sc.next();

        System.out.println("退出了主线程"+Thread.currentThread().getName());
    }

}


    class DaemonThread implements Runnable{
        private String filePath = "C:/Users/Administrator/Desktop/daemon.txt";

        @Override
        public void run() {
            System.out.println("进入了守护线程"+Thread.currentThread().getName());
            writeToFile();
            System.out.println("退出了守护线程"+Thread.currentThread().getName());
        }

        private void writeToFile() {
            OutputStream os = null;
            File filename = new File(filePath);
            try {
                os = new FileOutputStream(filename,true);
                int count = 0;
                while(count<999){
                    os.write(("\r\nword"+count).getBytes());
                    System.out.println("守护线程"+Thread.currentThread().getName()+"向文件中写入了word"+count++);
                    Thread.sleep(1000);
                }
            } catch (Exception e) {
                e.printStackTrace();
            }finally{
                try {
                    os.close();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }

    }

结果截图:
这里写图片描述
生成的文件内容截图:
这里写图片描述

通过这个例子:我们可以看到这个程序中只有一个用户线程也就是主线程,当主线程结束的时候,守护线程就会自动销毁(结果就是造成写入的文件不完成)。

通过jstack生成线程快照

jstack的路径位置:
位于jdk/bin目录下
作用:
生成JVM当前时刻线程的快照(threaddump,即当前进程中所有线程 的信息)
目的:
帮助定位程序问题出现的原因,如:长时间停顿,CPU占用率过高等。
使用方法:
在命令提示符中输入jstack,就会显示出jstack的使用帮助。
如图:
这里写图片描述
这里的-l可有可无,如果有就会打印出线程的一些锁的信息
pid:就是任务管理其中进程的标号
如图:当我启动刚才的程序的时候进程中就会多出一个javaw.exe的进程
这里写图片描述
图中可以看到PID一项,这里的PID就是我启动的上边的程序进程的标号。
使用jstack运行该程序的PID。如图:
这里写图片描述
说明:
绿色框中的是进程中其中一个线程的信息。绿框下面的每一段都表示一个现成的信息。
该图中线程状态的说明图:
这里写图片描述
该图中阻塞状态说明:
Blocked:如果一个线程正在等待一个监视器的锁,那个该线程就处于Blocked状态。eg: 被synchronized阻塞的线程
Waiting:如果一个线程正在无限期的等待另一个线程执行任务,那么这个线程就处于Waiting状态。eg:当线程调用join()方法的时候就会有个线程进入Waiting状态。
Timed_waiting:如果一个线程在指定的时间内等待另一个线程执行任务,那么这个线程就处于Timed_waiting状态。eg:当程序调用了sleep()方法,并在sleep()方法中指定了休眠时间(eg:sleep(1000)形式),那么这个线程就进入了Timed_waiting状态。

所以守护线程处于Timed_waiting状态的原因是,我们在守护线程中调用了sleep(1000)方法。如图:
这里写图片描述
继续解释命令提示符中的内容
这里写图片描述
继续查看主线程信息:
这里写图片描述
这里写图片描述

转自:http://blog.csdn.net/u013991521/article/details/47281223

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
基于微信小程序的家政服务预约系统采用PHP语言和微信小程序技术,数据库采用Mysql,运行软件为微信开发者工具。本系统实现了管理员和客户、员工三个角色的功能。管理员的功能为客户管理、员工管理、家政服务管理、服务预约管理、员工风采管理、客户需求管理、接单管理等。客户的功能为查看家政服务进行预约和发布自己的需求以及管理预约信息和接单信息等。员工可以查看预约信息和进行接单。本系统实现了网上预约家政服务的流程化管理,可以帮助工作人员的管理工作和帮助客户查询家政服务的相关信息,改变了客户找家政服务的方式,提高了预约家政服务的效率。 本系统是针对网上预约家政服务开发的工作管理系统,包括到所有的工作内容。可以使网上预约家政服务的工作合理化和流程化。本系统包括手机端设计和电脑端设计,有界面和数据库。本系统的使用角色分为管理员和客户、员工三个身份。管理员可以管理系统里的所有信息。员工可以发布服务信息和查询客户的需求进行接单。客户可以发布需求和预约家政服务以及管理预约信息、接单信息。 本功能可以实现家政服务信息的查询和删除,管理员添加家政服务信息功能填写正确的信息就可以实现家政服务信息的添加,点击家政服务信息管理功能可以看到基于微信小程序的家政服务预约系统里所有家政服务的信息,在添加家政服务信息的界面里需要填写标题信息,当信息填写不正确就会造成家政服务信息添加失败。员工风采信息可以使客户更好的了解员工。员工风采信息管理的流程为,管理员点击员工风采信息管理功能,查看员工风采信息,点击员工风采信息添加功能,输入员工风采信息然后点击提交按钮就可以完成员工风采信息的添加。客户需求信息关系着客户的家政服务预约,管理员可以查询和修改客户需求信息,还可以查看客户需求的添加时间。接单信息属于本系统里的核心数据,管理员可以对接单的信息进行查询。本功能设计的目的可以使家政服务进行及时的安排。管理员可以查询员工信息,可以进行修改删除。 客户可以查看自己的预约和修改自己的资料并发布需求以及管理接单信息等。 在首页里可以看到管理员添加和管理的信息,客户可以在首页里进行家政服务的预约和公司介绍信息的了解。 员工可以查询客户需求进行接单以及管理家政服务信息和留言信息、收藏信息等。
数字社区解决方案是一套综合性的系统,旨在通过新基建实现社区的数字化转型,打通智慧城市建设的"最后一公里"。该方案以国家政策为背景,响应了国务院、公安部和中央政法会议的号召,强调了社会治安防控体系的建设以及社区治理创新的重要性。 该方案的建设标准由中央综治办牵头,采用"9+X"模式,通过信息采集、案(事)件流转等手段,实现五级信息中心的互联互通,提升综治工作的可预见性、精确性和高效性。然而,当前社区面临信息化管理手段不足、安全隐患、人员动向难以掌握和数据资源融合难等问题。 为了解决这些问题,数字社区建设目标提出了"通-治-服"的治理理念,通过街道社区、区政府、公安部门和居民的共同努力,实现社区的平安、幸福和便捷。建设思路围绕"3+N"模式,即人工智能、物联网和数据资源,结合态势感知、业务分析和指挥调度,构建起一个全面的数据支持系统。 数字社区的治理体系通过"一张图"实现社区内各维度的综合态势可视化,"一套表"进行业务分析,"一张网"完成指挥调度。这些工具共同提升了社区治理的智能化和效率。同时,数字社区还提供了包括智慧通行、智慧环保、居家养老和便民服务等在内的多样化数字服务,旨在提升居民的生活质量。 在硬件方面,数字社区拥有IOT物联网边缘网关盒子和AI边缘分析盒子,这些设备能够快速集成老旧小区的物联设备,实现传统摄像设备的智能化改造。平台优势体现在数字化能力中台和多样化的应用,支持云、边、端的协同工作,实现模块化集成。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值