一、程序、进程、线程
.程序:程序就是我们编写的代码,也就是指令集,是一个静态概念。
.进程:操作系统调度我们的程序,动态概念,一个程序就是一个进程。进程是程序的一次动态执行过程,占用特定的地址空间,每个进程是独立的,由3部分组成:cpu,data(数据),code(代码区)。缺点:内存浪费,cpu会有负担。
.线程:是进程中的一个单一的执行路径,线程又被称为轻量级的进程。一个进程可以拥有多个并行的线程。一个进程中的线程共享内存单元/内存地址空间,多个线程可以共享数据,可以访问相同的变量和对象,是从同一堆中分配对象。所以有一个并发的问题,一份数据多个线程来用。由于线程间的通信是在同一地址空间进行,所以不需要额外的通信机制, 一个程序就有一个进程,每个进程有独立的代码和数据空间,进程间的切换有较大的开销。
多进程是操作系统能同时运行多个任务(程序),多线程是在同一应用程序中有多个执行流程。
系统为每个进程分配不同的内存区域,不会为线程分配内存(因为线程在进程中),线程是进程的一部分,所以线程也被成为轻量级进程。 线程在java中也是类和接口,进程包含线程,线程是进程的一部分,线程是不同的执行路径, 多线程就是有多核,多个cpu。cpu有一个调度,有一个时间片,时间片非常的小。main方法是一个主线程,就是一条路径。 线程创建的第一种方式:
/**
* 模拟龟兔赛跑
1、创建多线程 继承 Thread +重写run(线程体)
2、使用线程: 创建子类对象 + 对象.start() 线程启动
*/
public class Rabbit extends Thread {
@Override
public void run() {//线程体,一切从run开始就像main方法一切从main开始,这个运行一切从run开始。
for(int i=;i<;i++){
System.out.println("兔子跑了"+i+"步");
}
}
}
class Tortoise extends Thread {
@Override
public void run() {
//线程体
for(int i=;i<;i++){
System.out.println("乌龟跑了"+i+"步");
}
}
} public class RabbitApp {
public static void main(String[] args) {//main也是一个线程有自己的路径。
//创建子类对象
Rabbit rab = new Rabbit();
Tortoise tor =new Tortoise();
//调用start 方法,内部由cpu调用他们,start()只是加到线程里面。
rab.start();
//rab.run();//不要调用run方法,调用run方法不是启动线程而是普通方法的调用。程序会从上到下依次调用执行。
tor.start();
//tor.run();
for(int i=;i<;i++){
System.out.println("main==>"+i);
}
/*main==>96
main==>97
main==>98
main==>99
乌龟跑了0步
乌龟跑了1步
乌龟跑了2步
兔子跑了14步
兔子跑了15步
兔子跑了16步
兔子跑了17步*/ }//rab.start(); 和 tor.start();和 main()的for(int i=0;i<100;i++){System.out.println("main==>"+i);}3者交替执行
} 第二种实现多线程的方式:
继承Thread类方式的缺点是如果一个类已经从另一个类继承则无法再继承Thread类。
所以通过实现Runnable接口,有点是可以实现同时继承。
Runnable接口用到了静态代理设计模式,下面先看看静态代理设计模式。
/**
* 静态代理 设计模式(静态代理的时候WeddingCompany是写死的,动态代理的时候WeddingCompany是动态创建的,也就是说代理对象是动态的)(代理就是代别人做事,被代理就是别人做事都是做的自己的事)
* 代理的要求:
* 1、真实角色
* 2、代理角色: 持有真实角色的引用
* 3、二者 实现相同的接口(代理去实现这个方法也就是被代理的去实现这个方法)
*/
public class StaticProxy {
public static void main(String[] args) {
//创建真实角色
Marry you =new You();
//创建代理角色 +真实角色的引用
WeddingCompany company =new WeddingCompany(you);
//执行任务
company.marry();
}
}
//接口
interface Marry{
void marry();//相当于public abstract void marry();接口里面的方法都是公共的抽象的
}
//真实角色
class You implements Marry{
@Override
public void marry() {
System.out.println("you and 嫦娥结婚了....");
}
}
//代理角色
class WeddingCompany implements Marry{
private Marry you;
public WeddingCompany() {
}
public WeddingCompany(Marry you) {
this.you = you;
}
private void before(){
System.out.println("布置猪窝...."); }
private void after(){
System.out.println("闹玉兔....");
}
@Override
public void marry() {
before();
you.marry();
after();
}
} 静态代理 + Runnable接口实现多线程:
/**
推荐 Runnable 创建线程
1)、避免单继承的局限性(继承接口后还可以继承其他类)
2)、便于共享资源 使用 Runnable 创建线程
1、类 实现 Runnable接口 +重写 run() --> 真实角色类
2、启动多线程 使用静态代理
1)、创建真实角色
2)、创建代理角色 +真实角色引用
3)、调用 .start() 启动线程
*/
public class Programmer implements Runnable {
@Override
public void run() {
for(int i=;i<;i++){
System.out.println("一边敲helloworld....");
}
}
} public class ProgrammerApp {
public static void main(String[] args) {//main也是一个线程有自己的路径。
//1)、创建真实角色
Programmer pro =new Programmer();
//2)、创建代理角色 +真实角色引用
Thread proxy =new Thread(pro);//Thread和Programmer一样实现了Runnable接口,proxy代理别人做事,所以proxy是代理,Programmer是被代理。所以这里用到了静态代理模式。
//3)、调用 .start() 启动线程
proxy.start();
for(int i=;i<;i++){
System.out.println("一边聊qq....");
}
}
} /**
* 方便共享资源
*/
public class Web12306 implements Runnable {
private int num =;//50张票
@Override
public void run() {
while(true){
if(num<=){
break; //跳出循环
}
System.out.println(Thread.currentThread().getName()+"抢到了"+num--);
}
} public static void main(String[] args) {//这个线程的名字是main
//真实角色
Web12306 web = new Web12306();
//public class Thread implements Runnable {}
//静态代理模式,Thread和Web12306都实现了Runnable接口,
// public Thread(Runnable target, String name) {}
Thread t1 =new Thread(web,"路人甲");//线程t1的名字
Thread t2 =new Thread(web,"黄牛已");//线程t2的名字
Thread t3 =new Thread(web,"攻城师");//线程t3的名字
//启动线程
t1.start();//start()就启动了线程
t2.start();
t3.start();
/*路人甲抢到了9
黄牛已抢到了10
黄牛已抢到了8
黄牛已抢到了7
黄牛已抢到了6
黄牛已抢到了5
黄牛已抢到了3
黄牛已抢到了2
黄牛已抢到了1
攻城师抢到了4*/
}
} 线程:
一、继承Thread,重写run()方法,启动:创建子类对象+对象.start()
二、实现Runnable,重写run(),启动:使用静态代理,.创建真实角色,.创建代理角色(Thread),.代理角色.start() 实现Runnable,重写run()的缺点是不能拋异常,没有返回值,因此使用Callable接口解决这个问题。使用Callable创建线程比较繁琐,优点是又返回值并且可以对外申明异常。 通过Callable接口实现多线程
优点:可以获取返回值
Callable和Future接口,Callable是类似于Runnable的接口,实现Callable接口的类和实现Runnable接口的类都是可被其他线程执行的任务。
Callable和Runnable有几点不同:
.Callable规定的方法是call(),而Runnable规定的方法是run()
.call()可抛出异常,而run()是不能抛出异常的
.Callable的任务执行后可返回值,运行Callable任务可以拿到一个Future对象,而Runnable任务是不能返回值的,Future表示异步计算的结果。它提供了检查计算是否完成的方法,以等待计算的完成,并检索计算的结果。通过Future对象可以了解任务执行的情况,可取消任务的执行,还可以获取任务的执行结果。
缺点:繁琐
步骤:
.创建Callable实现类,重写call方法。
.借助执行调度服务ExecutorService获取Future对象。
ExecutorService ser=Executors.newFixedThreadPool();
Future result =ser.submit(实现类对象) ;
.获取值result.get();
.停止服务ser.shutdownNow(); import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
/**
* 使用Callable创建线程
*/
public class Call {
public static void main(String[] args) throws InterruptedException, ExecutionException {
//创建2个线程
ExecutorService ser=Executors.newFixedThreadPool(); Race tortoise = new Race("老不死",);
Future<Integer> result1 =ser.submit(tortoise) ;//让线程执行tortoise,获取值,
tortoise.setFlag(false); //停止线程体循环
int num1 =result1.get();//进入call方法
System.out.println("乌龟跑了-->"+num1+"步"); Race rabbit = new Race("小兔子",);
Future<Integer> result2 =ser.submit(rabbit) ;
rabbit.setFlag(false);
int num2 =result2.get();
System.out.println("小兔子跑了-->"+num2+"步"); Thread.sleep(); //2秒
ser.shutdownNow();//停止服务
}
} class Race implements Callable<Integer>{//继承Callable接口,重写call方法。
private String name ; //名称
private long time; //延时时间
private boolean flag =true;
private int step =; //步
public Race() {
} public Race(String name) {
super();
this.name = name;
}
public Race(String name,long time) {
super();
this.name = name;
this.time =time;
} @Override
public Integer call() throws Exception {//有返回值,并且可以申明异常。
while(flag){
Thread.sleep(time); //延时
step++;
}
return step;
} public String getName() {
return name;
} public void setName(String name) {
this.name = name;
} public long getTime() {
return time;
} public void setTime(long time) {
this.time = time;
} public boolean isFlag() {
return flag;
} public void setFlag(boolean flag) {
this.flag = flag;
} public int getStep() {
return step;
} public void setStep(int step) {
this.step = step;
}
} 线程的状态:
.线程创建。
.调用start()方法,线程进入就绪状态。
.cpu调度,线程进入运行状态。
.任务完成,线程终止。
.线程运行过程中,出现导致阻塞的事件,线程进入阻塞状态,阻塞解除后,线程又进入就绪状态。(阻塞接触后是进入就绪状态不是运行状态)。 线程干涉:
线程体通过标示符,外部通过条件调用。
public class StopDemo01 {
public static void main(String[] args) {
Study s =new Study();
new Thread(s).start(); //外部干涉
for(int i=;i<;i++){
if(==i){ //外部干涉
s.stop();
}
System.out.println("main.....-->"+i);
}
}
}
class Study implements Runnable{
//1)、线程类中 定义 线程体使用的标识
private boolean flag =true;
@Override
public void run() {
//2)、线程体使用该标识
while(flag){
System.out.println("study thread....");
}
}
//3)、对外提供方法改变标识
public void stop(){
this.flag =false;
}
} 阻塞:
.join:合并线程。
.yeld:暂停自己,让别的线程执行。
.sleep:休眠,休眠的时候不会释放锁。常用于与时间相关的和模拟网络延时。 /**
* join:合并线程
*/
public class JoinDemo01 extends Thread {
public static void main(String[] args) throws InterruptedException {
JoinDemo01 demo = new JoinDemo01();
Thread t = new Thread(demo); //新生
t.start();//就绪
//cpu调度 运行
for(int i=;i<;i++){
if(==i){
t.join(); //main阻塞...一定要等到t的线程执行完main才能开始执行。
}
System.out.println("main...."+i);
}
} @Override
public void run() {
for(int i=;i<;i++){
System.out.println("join...."+i);
}
}
} public class YieldDemo01 extends Thread {
public static void main(String[] args) {
YieldDemo01 demo = new YieldDemo01();
Thread t = new Thread(demo); //新生
t.start();//就绪
//cpu调度 运行
for(int i=;i<;i++){
if(i%==){
//暂停本线程 main,yield是一个静态方法,写在哪个线程体里面就暂停谁。之后什么时候再次调用是由cpu的调度算法决定的。
Thread.yield();
}
System.out.println("main...."+i);
}
} @Override
public void run() {
for(int i=;i<;i++){
System.out.println("yield...."+i);
}
}
} /**
* 倒计时
* 1、倒数10个数,一秒内打印一个
* 2、倒计时
*/
public class SleepDemo01 {
public static void main(String[] args) throws InterruptedException {
Date endTime =new Date(System.currentTimeMillis()+*);//当前时间加上10秒
long end =endTime.getTime();
while(true){
//输出
System.out.println(new SimpleDateFormat("mm:ss").format(endTime));
//等待一秒
Thread.sleep();
//构建下一秒时间
endTime =new Date(endTime.getTime()-);
//10秒以内 继续 否则 退出
if(end->endTime.getTime()){
break;
}
}
/*17:56 17:55 17:54 17:53 17:52 17:51 17:50 17:49 17:48 17:47 17:46*/
}
public static void test1() throws InterruptedException{
int num =;
while(true){
System.out.println(num--);
Thread.sleep(); //暂停
if(num<=){
break;
}
}
}
} /**
* Sleep模拟 网络延时 线程不安全的类
*/
public class SleepDemo02 {
public static void main(String[] args) {
//真实角色
Web12306 web= new Web12306();
Web12306 web2 = new Web12306();
//3个代理同时操控一个被代理对象,
Thread t1 =new Thread(web,"路人甲");
Thread t2 =new Thread(web,"黄牛已");
Thread t3 =new Thread(web,"攻城师");
//启动线程
t1.start();
t2.start();
t3.start();
} } class Web12306 implements Runnable {
private int num =; @Override
public void run() {
while(true){
if(num<=){//num=1时,当a、b、c依次进来后依次开始睡眠。
break; //跳出循环
}
try {
Thread.sleep();///sleep也是暂停线程的一种方式.休眠的时候不会释放锁,
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+"抢到了"+num--);
}//a醒了以后带走了1,b醒了以后带走了0,c醒了以后带走了-1。
}
}

java16 程序、进程、线程的更多相关文章

  1. System、应用程序进程的Binder线程池和Handler消息循环

    首先看一张Android系统启动流程图:

  2. Linux进程线程学习笔记:运行新程序

    Linux进程线程学习笔记:运行新程序                                         周银辉 在上一篇中我们说到,当启动一个新进程以后,新进程会复制父进程的大部份上下 ...

  3. python学习笔记-进程线程

    1.什么是进程(process)? 程序并不能单独运行,只有将程序装载到内存中,系统为它分配资源才能运行,而这种执行的程序就称之为进程.程序和进程的区别就在于:程序是指令的集合,它是进程运行的静态描述 ...

  4. 获取系统中所有进程&线程信息

    读书笔记--[计算机病毒解密与对抗] 目录: 遍历进程&线程程序 终止进程 获取进程信息 获取进程内模块信息 获取进程命令行参数 代码运行环境:Win7 x64 VS2012 Update3 ...

  5. pyhon——进程线程、与协程基础概述

    一直以来写博客都是实用主义者,只写用法,没信心写原理,但是每一次写作业的过程都有一种掘地三尺的感觉,终于,写博客困难症重症患者经历了漫长的思想斗争,还是决定把从网上淘到的各种杂货和自己的总结放在一起, ...

  6. android 进程/线程管理(一)----消息机制的框架

    一:android 进程和线程 进程是程序运行的一个实例.android通过4大主件,弱化了进程的概念,尤其是在app层面,基本不需要关系进程间的通信等问题. 但是程序的本质没有变,尤其是多任务系统, ...

  7. android 进程/线程管理(二)----关于线程的迷思

    一:进程和线程的由来 进程是计算机科技发展的过程的产物. 最早计算机发明出来,是为了解决数学计算而发明的.每解决一个问题,就要打纸带,也就是打点. 后来人们发现可以批量的设置命令,由计算机读取这些命令 ...

  8. windows进程/线程创建过程 --- windows操作系统学习

    有了之前的对进程和线程对象的学习的铺垫后,我们现在可以开始学习windows下的进程创建过程了,我将尝试着从源代码的层次来分析在windows下创建一个进程都要涉及到哪些步骤,都要涉及到哪些数据结构. ...

  9. Android应用程序进程启动过程的源代码分析

    文章转载至CSDN社区罗升阳的安卓之旅,原文地址: http://blog.csdn.net/luoshengyang/article/details/6747696 Android 应用程序框架层创 ...

  10. Linux查看进程线程个数

    1.根据进程号进行查询: # pstree -p 进程号 # top -Hp 进程号 2.根据进程名字进行查询: # pstree -p `ps -e | grep server | awk '{pr ...

随机推荐

  1. 【HDOJ】1045 Fire Net

    经典深搜.注意满足条件. #include <stdio.h> #include <string.h> #define MAXNUM 5 char map[MAXNUM][MA ...

  2. c程序设计语言_习题1-9_将输入流复制到输出流,并将多个空格过滤成一个空格

    Write a program to copy its input to its output, replacing each string of one or more blanks by a si ...

  3. 一个TextView使用不同的颜色

    一个TextView使用不同的颜色: textview中首先需要已经有内容了 public static void ColorFormatTextView(TextView tv,int color, ...

  4. chrome的timeline的问题?

    如图:Stalled.RequestSent等所表达的是什么意思呢? Stalled是浏览器得到要发出这个请求的指令,到请求可以发出的等待时间,一般是代理协商.以及等待可复用的TCP连接释放的时间,不 ...

  5. selenium2.0 处理各种窗口问题解决方法

    selenium2.0处理muti-Windows . Frames .Popup Dialogs selenium2.0处理多窗口,弹窗等,只需要调用WebDriver 嵌套类:TargetLoca ...

  6. Nginx反向代理+DNS轮询+IIS7.5 千万PV 百万IP 双线 网站架构案例

    原文地址:http://www.jb51.net/article/31844.htm Nginx  ("engine x") 是一个高性能的 HTTP 和反向代理服务器,也是一个 ...

  7. 【JS】Beginner2:Variables & Data

    1.Variables name :name it in a way that tells what you've stored there value: 2.Create a variable =& ...

  8. PHP字符串替换函数strtr()

    strtr函数比str_replace函数的效率要高很多,strtr()的两种定义方式: strtr(string, from, to)和strtr(string, array)1.strtr区分大小 ...

  9. Linux下安装mysql5.6.11(找点有用的信息太费劲)(转)

    Linux下安装mysql5.6.11(找点有用的信息太费劲) (2013-04-25 10:25:09)     1.申请阿里云Linux服务器 昨天在阿里云申请了一个免费试用5天的Linux云服务 ...

  10. Weka 入门3

    这次我们介绍Evaluation类.在上一次中我们只是单纯的预测了分类值,并没有其他评价数据.这场我们使用Evalution类.首先初始化一个Evaluation对象,Evaluation类没有无参的 ...