1.1、进程

正在执行的程序称作为一个进程.进程负责了内存空间的划分

 疑问1:windows电脑称之为多任务的操作系统,那么Windows是同时运行多个应用程序呢?
从宏观的角度:windows确实在同时运行多个程序.
从微观的角度:cpu是做一个快速的切换执行的动作,速度太快,所以你感觉不到切换而已.

1.2、线程

线程在一个进程中负责了代码的执行,进程中的一个执行路径

1.3、多线程

在一个进程中有多个线程同时在执行不同的任务

疑问2:线程负责了代码的执行,我们之前没有学过线程,为什么代码可以执行?
任何一个java程序,在jvm运行时都会创建一个main线程执行main方法中的所有代码.

1.4、多线程好处

1.解决一个进程中能执行多个任务的问题.
    2.提高了资源的利用率

1.5、多线程弊端

1.增加了cpu的负担
    2.降低了一个进程中的线程执行的概率
    3.引发了线程安全问题
    4.出现死锁的现象

1.6、创建多线程的方式

方式一:
    1.自定义一个类继承Thread类
    2.重写Thread的类里面的run方法,自定义线程的代码写在run方法里面
    3.创建Thread的子类对象,并且调用start方法开启线程.

注意:一个线程一旦开启,那么这个线程就会执行run方法中的代码,run方法千万不要直接调用,如果直接调用它就相当于一个普通方法,就不会开启新的线程。

疑问3: 重写run方法的目的是什么?
每个线程都有自己的任务代码,jvm创建主线程的任务代码就是main方法中的所有代码,自定义线程的任务代码,需要写在run方法里面,自定线程负责run方法中的代码

方式二:
    1.自定义一个类实现Runnable接口
    2.实现Runnable里面的run方法,把自定义线程的任务定义在run方法里面
    3.创建Runnable实现类对象
    4.创建Thread对象,并且把Runnable实现类对象作为参数传递
    5.调用Thread对象的start方法开启一个线程

推荐使用:第二种 实现Runnable接口的方式;因为java单继承,多实现

问题4:请问Runnable实现对象是线程对象吗?
答:Runnable实现类对象并不是一个线程对象,只不过实现了Runnable接口的对象而已,只有Thread或者Thread的子类才是线程对象
问题5:为啥要把Runnable实现类对象作为参数传递给Thread对象呢?作用是什么?
答:作用就是把Runnable实现类对象的run方法作为线程的任务代码去执行了.

1.7、实例

 package com.zn.thread;

 /**
* @author DSHORE / 2018-5-3
* 方式1的实例
*/
/*创建多线程的方式
* 方式一:
* 1.自定义一个类继承Thread类
* 2.重写Thread的类里面的run方法,自定义线程的代码写在run方法里面
* 3.创建Thread的子类对象,并且调用start方法开启线程.
*
* 注意:一个线程一旦开启,那么这个线程就会执行run方法中的代码,run方法千万不要直接调用,如果直接调用它就相当于一个普通方法,就不会开启新的线程.
*
* */
public class Demo1 extends Thread {//1.自定义一个类继承Thread类
@Override
public void run() {//2.重写Thread的类里面的run方法,自定义线程的代码写在run方法里面
for(int i=;i<;i++){
System.out.println("自定义线程"+i);
}
}
public static void main(String[] args) {
Demo1 d=new Demo1();//3.创建Thread的子类对象,并且调用start方法开启线程.
d.start(); for(int i=;i<;i++){
System.out.println("主线程"+i);
}
}
}

运行结果图: 注:每次的运行结果都不一样,线程问题

 package com.zn.thread;

 /**
* @author DSHORE / 2018-5-3
* 方式2的实例
*/
/*方式二:
* 1.自定义一个类实现Runnable接口
* 2.实现Runnable里面的run方法,把自定义线程的任务定义在run方法里面
* 3.创建Runnable实现类对象
* 4.创建Thread对象,并且把Runnable实现类对象作为参数传递
* 5.调用Thread对象的start方法开启一个线程
*
* 推荐使用:第二种 实现Runnable接口的方式;因为java单继承,多实现
*/
class Test implements Runnable{ @Override
public void run() { for(int i=;i<;i++){
System.out.println(Thread.currentThread().getName()+i);
}
}
}
public class Demo2 { public static void main(String[] args) {
//创建Runnable实现类对象
Test t=new Test();
//创建Thread对象,并且把Runnable实现类对象作为参数传递
Thread d=new Thread(t,"二狗子");
//调用Thread对象的start方法开启一个线程
d.start();
for (int i = ; i <; i++) {
System.out.println(Thread.currentThread().getName()+i);
}
}
}

运行结果图

1.8、线程的生命周期 图解

线程生命周期的五种状态:

    1、新建(new Thread):当程序使用new关键字创建了一个线程之后,该线程就处于新建状态,此时仅由JVM为其分配内存,并初始化其成员变量的值

    2、就绪(runnable)当线程对象调用了start()方法之后,该线程处于就绪状态。Java虚拟机会为其创建方法调用栈和程序计数器,等待调度运行

    3、运行(running)如果处于就绪状态的线程获得了CPU,开始执行run()方法的线程执行体,则该线程处于运行状态

    4、堵塞(blocked)当处于运行状态的线程失去所占用资源之后(正在运行的线程让出CPU并暂停自己的执行),便进入阻塞状态

    5、死亡(dead)线程run()、main() 方法执行结束,或者因异常退出了run()方法,则该线程结束生命周期。死亡的线程不可再次复生。

线程生命周期详解:https://www.cnblogs.com/sunddenly/p/4106562.html  或  https://blog.csdn.net/pange1991/article/details/53860651

下面是:wait()、notify()、notifyAll()、interrupt()、setDaemon()、join() 等方法的使用

 package com.zn.thread;

 /*
* 线程的通讯:一个线程完成了自己的任务时,要通知另一个线程去完成另一个任务
*
* 生产者与消费者
*
* wait():等待。如果线程执行到了wait方法,那么该线程会进入等待状态,等待状态下的线程必须要被其他线程调用notify()方法才能唤醒.
* notify():唤醒。唤醒线程池等待的其中一条线程
* notifyAll(): 唤醒线程池中所等待的线程
* */
//产品
class Product{
String name;//产品名字
double price;//价格
boolean flag=false;//生产者是否生产完成的标志,默认是没有生产完成
}
//生产者
class Producer extends Thread{
Product p;
public Producer(Product p) {
this.p=p;
}
@Override
public void run() {
int i=;
while(true){
synchronized (p) {
if(p.flag==false){
if(i%==){
p.name="苹果";
p.price=5.0;
}else{
p.name="香蕉";
p.price=3.5;
}
System.out.println("生存者生产出了:"+p.name+"; 价格是:"+p.price);
p.flag=true;//flag为true时,通知消费者去消费
i++;
p.notify();//唤醒 消费者去消费
}else{
try {
p.wait();//生产者等待
} catch (InterruptedException e) {
e.printStackTrace();//打印异常信息
}
}
}
}
}
}
//消费者
class Customer extends Thread{
Product p;
public Customer(Product p) {
this.p=p;
}
@Override
public void run() {
while(true){
synchronized (p) {
if(p.flag==true){
System.out.println("消费者消费了:"+p.name+"; 价格:"+p.price);
p.flag=false;//flag为false时,通知生产者去生产
p.notify();//唤醒 生产者去生产
}else{
try {
p.wait();//消费者也等待了
} catch (InterruptedException e) {
e.printStackTrace();//打印异常信息
}
}
}
}
}
}
public class Demo5 {
public static void main(String[] args) {
Product p=new Product();
//创建线程对象
Producer producer=new Producer(p);
Customer customer=new Customer(p);
//开启线程
producer.start();
customer.start();
}
}
 package com.zn.thread;
/*停止线程:
* 1.停止一个线程 我们一般都会通过一个变量去控制
* 2.如果需要停止一个处于等待状态的线程,那么我们需要通过变量配合notify方法或者interrupt()来使用
* */
public class Demo2 extends Thread{
boolean flag=true;
public Demo2(String name) {
super(name);
}
@Override
public synchronized void run() {
int i=;
while(flag){
System.out.println("嘿,你好"+Thread.currentThread().getName()+":"+i);
i++;
}
}
public static void main(String[] args) {
Demo2 d=new Demo2("狗娃");
d.start();
System.out.println("");
for (int i = ; i <; i++) {
d.flag=false;
d.interrupt(); //interrupt():调用该方法后,该线程被置于"中断状态"
}
}
}
 package com.zn.thread;
/*
* 保护线程(后台线程):在一个进程中如果只剩下了守护线程,那么守护线程也会死亡
* 需求:模拟QQ下载更新包
*
* */
public class Demo3 extends Thread{
public Demo3(String name){
super(name);
}
@Override
public void run() {
for (int i = ; i <=; i++) {
System.out.println("更新包目前下载"+i+"%");
if(i==){
System.out.println("下载完毕");
}
}
try {
Thread.sleep();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public static void main(String[] args) {
Demo3 d=new Demo3("后台线程");
d.setDaemon(true);//将该线程标记为守护线程或用户线程,该方法必须在启动线程前调用
System.out.println(d.isDaemon());
d.start();
for (int i = ; i <=; i++) {
System.out.println(Thread.currentThread().getName()+":"+i);
}
}
}

join()  方法

 package com.zn.thread;

 /**
* @author DSHORE / 2018-5-14
*
*/
/*
* join()方法:加入
*
* 需求:在没加油处插入去买酱油的过程,顺序要正确
*
* */ //老妈
class Mon extends Thread{
@Override
public void run() {
System.out.println("妈妈洗菜");
System.out.println("妈妈切菜");
System.out.println("妈妈准备炒菜,发现没酱油了");
Son s=new Son();
s.start();
try {
s.join();//加入,一个线程如果执行join语句,那么就会有新的线程加入,执行该语句的线程必须要让步给新加入的线程完成任务,然后才能继续执行
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("妈妈继续炒菜");
System.out.println("全家一起卡饭...");
}
}
//儿子
class Son extends Thread{
@Override
public void run() {
System.out.println("让儿子下楼去买");
System.out.println("儿子买完酱油");
System.out.println("上楼把酱油给老妈");
}
}
public class Demo8 {
public static void main(String[] args) {
Mon m=new Mon();
m.start();
}
}

运行结果图

          

原创作者:DSHORE

作者主页:http://www.cnblogs.com/dshore123/

原文出自:http://www.cnblogs.com/dshore123/p/8984060.html

欢迎转载,转载务必说明出处。(如果本文对您有帮助,可以点击一下右下角的 推荐,或评论,谢谢!

java基础24 线程、多线程及线程的生命周期(Thread)的更多相关文章

  1. Java基础加强之多线程篇(线程创建与终止、互斥、通信、本地变量)

    线程创建与终止 线程创建 Thread类与Runnable接口的关系 public interface Runnable { public abstract void run(); } public ...

  2. JAVA基础知识之多线程——控制线程

    join线程 在某个线程中调用其他线程的join()方法,就会使当前线程进入阻塞状态,直到被join线程执行完为止.join方法类似于wait, 通常会在主线程中调用别的线程的join方法,这样可以保 ...

  3. Java基础知识(多线程和线程池)

    新建状态: 一个新产生的线程从新状态开始了它的生命周期.它保持这个状态直到程序 start 这个线程. 运行状态:当一个新状态的线程被 start 以后,线程就变成可运行状态,一个线程在此状态下被认为 ...

  4. Java基础教程:多线程基础(2)——线程间的通信

    Java基础教程:多线程基础(2)——线程间的通信 使线程间进行通信后,系统之间的交互性会更强大,在大大提高CPU利用率的同时还会使程序员对各线程任务在处理的过程中进行有效的把控与监督. 线程间的通信 ...

  5. Java基础教程:多线程基础——线程池

    Java基础教程:多线程基础——线程池 线程池 在正常负载的情况瞎,通过为每一个请求创建一个新的线程来提供服务,从而实现更高的响应性. new Thread(runnable).start() 在生产 ...

  6. Java基础图解,JVM,线程,Spring,TCP,SpringMVC等开发体系图解

    Java基础图解,JVM,线程,Spring,TCP,SpringMVC等开发体系图解 1.Java虚拟机运行时数据区图 2. 堆的默认分配图 3.方法区结构图 4.对象的内存布局图 5.对象头的Ma ...

  7. Java基础教程:多线程基础(1)——基础操作

    Java:多线程基础(1) 实现多线程的两种方式 1.继承Thread类 public class myThread extends Thread { /** * 继承Thread类,重写RUN方法. ...

  8. Java基础教程:多线程基础(4)——Lock的使用

    Java基础教程:多线程基础(4)——Lock的使用 快速开始 Java 5中Lock对象的也能实现同步的效果,而且在使用上更加方便. 本节重点的2个知识点是:ReentrantLock类的使用和Re ...

  9. Java基础教程:多线程杂谈——双重检查锁与Volatile

    Java基础教程:多线程杂谈——双重检查锁与Volatile 双重检查锁 有时候可能需要推迟一些高开销的对象初始化操作,并且只有在使用这些对象时才进行初始化.此时程序员可能会采用延迟初始化.但要正确实 ...

  10. Java基础教程:多线程基础(5)——倒计时器(CountDownLatch)

    Java基础教程:多线程基础(5)——倒计时器(CountDownLatch) 引入倒计时器 在多线程协作完成业务功能时,有时候需要等待其他多个线程完成任务之后,主线程才能继续往下执行业务功能,在这种 ...

随机推荐

  1. 方程式EQGRP_Lost_in_Translation工具之fb.py

    使用方法: 环境搭建:win2003下测试: 下载python2.6并安装 下载pywin32并安装 将C:\Python26添加到环境变量PATH中 将整个windows目录复制到windows20 ...

  2. 响应式开发(二)-----Bootstrap框架的介绍

    简介 Bootstrap,来自 Twitter,是目前最受欢迎的前端框架,是一个用于快速开发 Web 应用程序和网站的前端框架.Bootstrap 是基于 HTML.CSS.JAVASCRIPT 的, ...

  3. 笛卡尔树Cartesian Tree

    前言 最近做题目,已经不止一次用到笛卡尔树了.这种数据结构极为优秀,但是构造的细节很容易出错.因此写一篇文章做一个总结. 笛卡尔树 Cartesian Tree 引入问题 有N条的长条状的矩形,宽度都 ...

  4. c/c++基本数据类型转换

    If either operand is of type long double, the other operand is converted to type long double. If the ...

  5. laravel 中的 toSql 获取带参数的 sql 语句

    默认情况下,toSql 获取到的 sql 里面的参数使用 "?" 代替的,如下: DB::table('user')->where('id', 1)->toSql(); ...

  6. hibernate的懒加载

    WHY? WHAT? HOW? 所谓懒加载(lazy)就是延时加载,延迟加载.即不是不加载,而是在需要的时候才加载. 什么时候用懒加载呢,我只能回答要用懒加载的时候就用懒加载. 至于为什么要用懒加载呢 ...

  7. 《编程快速上手》--web抓取--利用webbrowser模块的mapIT.py

    1.代码如下 #! python3 # mapIT.py - Launches a map in the browser using an address from the # command lin ...

  8. Python面向对象补充以及异常处理

    面向对象相关内容 一.isinstance(obj, cls) 检查是否obj是否是类 cls 的对象 class Foo(object): pass obj = Foo() isinstance(o ...

  9. python 中的os模块

    python os模块   Python os 模块提供了一个统一的操作系统接口函数 一.对于系统的操作 1.os.name 当前使用平台 其中 ‘nt’ 是 windows,’posix’ 是lin ...

  10. Mac下Clang编译libcurl

    使用终端进入curl的根目录下,执行 ./configre CC=clang make make install 之后前往/usr/local/lib下生成了libcurl.a和相应的动态库,头文件在 ...