/*
多线程: 进程:正在执行中的程序,一个应用程序启动后在内存中运行的那片空间。进程具有动态性和并发性。 线程:进程中的一个执行单元。负责进程中的程序的运行的。一个进程中至少要有一个线程。
一个进程中是可以有多个线程的,这个应用程序也可以称之为多线程程序。 程序启动了多线程,有什么应用呢?
可以实现多部分程序同时执行。专业术语称之为 并发。 多线程的使用可以合理使用cpu的资源,如果线程过多会导致降低性能。 cpu在处理程序时是通过快速切换完成的。在我们看来好像随机一样。
*/
 //03-多线程-主线程的运行方式&创建线程的第一种方式。
/*
通过代码来演示之前和之后的区别。 在之前的代码中,jvm启动后,必然有一个执行路径(线程)从main方法开始的,
一直执行到main方法结束。这个线程在java中称之为主线程。 当主线程在这个程序中执行时,如果遇到了循环而导致停留时间过长,
就无法执行下面的程序。
可不可以实现一个主线程负责执行其中一个循环,由另一个线程负责其他代码的执行。
实现多部分的代码同时执行。
这就是多线程技术可以解决的问题。 该如何创建线程呢? 通过API中的英文Thread搜索。查到了Thread类。
通过阅读Thread类中的描述。
创建线程有两种方式。
1,继承Thread类。
1.1 定义一个类去继承Thread.
1.2 重写run方法。
1.3 创建子类对象。就是创建线程对象。
1.4 调用strat方法。开启线程并让线程执行,同时还会告诉jvm调用run方法。 为什么要这么做?
继承Thread类:因为Thread类描述线程事物,具备线程应该有的功能。
那为什么不直接创建Thread类的对象呢?
Thread t1 = new Thread();
t.strat();//这么做没有错,但是该strat调用的是Thread类中的run方法,
而这个run方法没有做什么事情,更重要的是这个run方法中并没有定义我们需要让
线程执行的代码。 创建线程的目的是什么?是为了建立单独的执行路径,让多部分代码实现同时执行。
也就是线程创建并执行需要给定代码(线程的任务)。
对于之前所讲的主线程,它的任务定义在了主函数中。
自定义的线程需要执行的任务都定义在run方法中。
Thread类中run方法内部的任务并不是我们所需要的。只要重写这个run方法就行了。
既然Thread类已经定义了线程任务的位置,只要在位置中定义任务代码即可。
所以进行了重写run方法动作。 多线程执行时,在栈内存中,其实每一个执行线程都有一片自己所属的栈内存空间。
进行方法的压栈和弹栈。 当执行线程的任务结束了,线程自动在栈内存中释放了。
当所有的执行线程都结束了,进程就结束了。 //获取线程名称。可以通过Thread类中的一个currentThreadd()方法。怎么获取名称呢?
getName(); Thread.currentThread().getName(); 主线程的名称是:main
自定义的线程名称是:Thread-1 线程多个时,数字依次递增。
*/ class Demo extends Thread
{
private String name;
Demo(String name)
{
this.name = name;
}
public void run()
{
//int[] arr = new int[3];
//System.out.println(arr[4]);
for(int x=1;x<=20;x++)
{
System.out.println("name="+name+"....."+Thread.currentThread().getName()+".."+x);
}
}
} class ThreadDemo1
{
public static void main(String[] args)
{
//创建了两个线程对象。
Demo d1 = new Demo("小强");
Demo d2 = new Demo("旺财");
d2.start();//将d2这个线程开启。
d1.run();//由主线程负责。 /*
线程对象调用run方法和调用start方法的区别?
调用run方法不开启线程,仅是对象调用方法。
调用start开启线程,并让jvm调用run方法在开启的线程中执行。
*/
}
}
 //创建线程的第二种方式。
/*
创建线程的第二种方式:使用Runnable接口。
1,定义类实现Runnable接口。//避免了单继承的局限性。
2,覆盖接口中的run方法。将线程任务代码定义到run方法中。
3,创建Thread类的对象。 //只有创建Thread类的对象才可以创建线程。
4,将Runnable接口的子类对象作为参数传递给Thread类的构造函数。
因为线程任务已被封装到Runnable接口的run方法中,而这个run方法所属于Runnable接口的子类对象。
所以将这个子类对象作为参数传递给Thread的构造函数,这样,线程对象创建时就可以明确要运行的任务。
5,调用Thread类的strat方法开启线程。 第二种方式实现Runnable接口避免了单继承的局限性。所以,较为常用。
实现Runnable接口的方式,更加的符合面向对象,线程分为两部分,一部分线程对象,一部分线程任务。
继承Thread类,线程对象和线程任务耦合在一起,一旦创建Thread类的子类对象,既是线程对象,又有线程任务。
实现Runnable接口,将线程任务单独分离出来封装成对象。类型就是Runnable接口类型。
Runnable接口对线程对象和线程任务解耦。 //通过源代码的形式讲解了一些Runnable接口的子类对象作为参数传递给Thread构造函数的原因。
class Thread{
private Runnable target; Thread(Runnable traget)
{
this.target = target;
}
public void run() {
if (target != null) {
target.run();
}
}
public void strat()
{
run();
}
} Demo d = new Demo();//Runnable d = new Demo();
Thread t = new Thread(d);
t.strat();
*/ class Demo implements Runnable
{
private String name;
Demo(String name)
{
this.name = name;
}
//覆盖了接口Runnable的run方法。
public void run()
{
for(int x=1;x<20;x++)
{
System.out.println("name="+name+"....."+Thread.currentThread().getName()+".."+x);
}
}
}
class ThreadDemo2
{
public static void main(String[] args)
{
//创建Runnable子类的对象。注意它并不是线程对象。
Demo d = new Demo("Demo");
//创建Thread类的对象,将Runnable接口的子类对象作为参数传递给Thread类的构造函数。
Thread t1 = new Thread(d);
Thread t2 = new Thread(d);
t1.start();
t2.start(); System.out.println(Thread.currentThread().getName()+"------>");
}
}
 //多线程的安全问题产生及原因以及解决思路
/*
案例:售票的例子。 售票的动作需要同时执行。所以要使用多线程技术。 发生了线程安全问题,出现了错误的数据;0 -1 -2 问题产生的原因:
1,线程任务在操作共享的数据。
2,线程任务操作共享数据的代码有多条(运算有多个)。 解决思路:
只要让一个线程在执行线程任务时,将多条操作共享数据的代码执行完,
在执行过程中,不要让其他线程参与运算就行了。 代码体现:
Java中解决此问题通过代码块来完成的,
这个代码代码块称之为同步代码块 synchronized
格式:
synchronized(对象)
{
//需要被同步的代码。
} 同步好处:同步代码块解决了多线程安全问题。 同步的弊端:
降低了程序的性能。 同步前提:
必须保证多个线程在同步中使用的是同一个锁
解决了什么问题?当多线程安全问题发生时,加入了同步后,问题依旧发生时,
就要通过这个同步的前提来判断同步是否正确。
*/ class Ticket implements Runnable
{
//1,描述票的数量
private int tickets = 100; //2,售票的动作。这个动作需要被多线程执行,那就是线程任务代码,
//需要定义在run方法中。
//记住,线程任务中通常都有循环结构。
private Object obj = new Object();
public void run()
{
while(true)
{
synchronized(obj)//如果写 new Object() 则用的就不是同一个锁。
{
if(tickets > 0)
{
//要让线程在这里稍停,模拟问题的发生。sleep 看到了 0 -1 -2 这样的错误的数据,这就是传说中的安全问题。
try{Thread.sleep(1);}catch(InterruptedException e){/*未写处理方式,后面讲*/} System.out.println(Thread.currentThread().getName()+"...."+tickets--);//打印线程名称
}
}
}
}
} class ThreadDemo3
{
public static void main(String[] args)
{
//1,创建Runnable接口的子类对象。
Ticket t = new Ticket(); //创建四个线程对象。并将Runnable接口的子类对象作为参数传递给Thread的构造函数。
Thread t1 = new Thread(t);
Thread t2 = new Thread(t);
Thread t3 = new Thread(t);
Thread t4 = new Thread(t); //3,开启四个线程
t1.start();
t2.start();
t3.start();
t4.start();
}
}

《day14---多线程入门_进阶》的更多相关文章

  1. 简单物联网:外网访问内网路由器下树莓派Flask服务器

    最近做一个小东西,大概过程就是想在教室,宿舍控制实验室的一些设备. 已经在树莓上搭了一个轻量的flask服务器,在实验室的路由器下,任何设备都是可以访问的:但是有一些限制条件,比如我想在宿舍控制我种花 ...

  2. 利用ssh反向代理以及autossh实现从外网连接内网服务器

    前言 最近遇到这样一个问题,我在实验室架设了一台服务器,给师弟或者小伙伴练习Linux用,然后平时在实验室这边直接连接是没有问题的,都是内网嘛.但是回到宿舍问题出来了,使用校园网的童鞋还是能连接上,使 ...

  3. 外网访问内网Docker容器

    外网访问内网Docker容器 本地安装了Docker容器,只能在局域网内访问,怎样从外网也能访问本地Docker容器? 本文将介绍具体的实现步骤. 1. 准备工作 1.1 安装并启动Docker容器 ...

  4. 外网访问内网SpringBoot

    外网访问内网SpringBoot 本地安装了SpringBoot,只能在局域网内访问,怎样从外网也能访问本地SpringBoot? 本文将介绍具体的实现步骤. 1. 准备工作 1.1 安装Java 1 ...

  5. 外网访问内网Elasticsearch WEB

    外网访问内网Elasticsearch WEB 本地安装了Elasticsearch,只能在局域网内访问其WEB,怎样从外网也能访问本地Elasticsearch? 本文将介绍具体的实现步骤. 1. ...

  6. 怎样从外网访问内网Rails

    外网访问内网Rails 本地安装了Rails,只能在局域网内访问,怎样从外网也能访问本地Rails? 本文将介绍具体的实现步骤. 1. 准备工作 1.1 安装并启动Rails 默认安装的Rails端口 ...

  7. 怎样从外网访问内网Memcached数据库

    外网访问内网Memcached数据库 本地安装了Memcached数据库,只能在局域网内访问,怎样从外网也能访问本地Memcached数据库? 本文将介绍具体的实现步骤. 1. 准备工作 1.1 安装 ...

  8. 怎样从外网访问内网CouchDB数据库

    外网访问内网CouchDB数据库 本地安装了CouchDB数据库,只能在局域网内访问,怎样从外网也能访问本地CouchDB数据库? 本文将介绍具体的实现步骤. 1. 准备工作 1.1 安装并启动Cou ...

  9. 怎样从外网访问内网DB2数据库

    外网访问内网DB2数据库 本地安装了DB2数据库,只能在局域网内访问,怎样从外网也能访问本地DB2数据库? 本文将介绍具体的实现步骤. 1. 准备工作 1.1 安装并启动DB2数据库 默认安装的DB2 ...

  10. 怎样从外网访问内网OpenLDAP数据库

    外网访问内网OpenLDAP数据库 本地安装了OpenLDAP数据库,只能在局域网内访问,怎样从外网也能访问本地OpenLDAP数据库? 本文将介绍具体的实现步骤. 1. 准备工作 1.1 安装并启动 ...

随机推荐

  1. 经验解决Fragment被Replace后仍旧可见的问题

    经验解决Fragment被Replace后仍旧可见的问题 网上问的问题,大多会提到替换了Fragment而发现之前被替换的仍旧显示在那里.我个人使用android 2.3 +support 开发包,在 ...

  2. 线性表 - 从零开始实现by C++

    参考链接:数据结构探险之线性表篇     线性表

  3. 关于ipxe启动的几个疑问

    关于ipxe启动的几个疑问 http://bbs.wuyou.net/forum.php?mod=viewthread&tid=373026&page=1&extra=#pid ...

  4. IE7局部滚动区域下绝对定位或相对定位元素不随滚动条滚动的bug

    尽管在项目中测试人员已经慢慢淡化了IE6的测试,但是IE7依然还是要纳入测试范围. 最近碰到一个IE7的蛋疼bug,在页面上设置了一个局部的滚动区域,在拖动滚动条的时候,滚动区域内设置了相对定位或绝对 ...

  5. 用excel处理重复数据

    我们在处理数据时,重复数据常常会对分析造成很大麻烦,因此数据整理初期一个重要的工作是排重,excel2007以上版本中有一个删除重复项功常便捷,但是每次点来点去也很麻烦,下面我们用公式来对一些重复数据 ...

  6. tableview调用reloadData()之后界面不刷新显示

    解决方法: 查看是否有指定tableView的delegate和datasource. self.tableView.delegate = self self.tableView.datasource ...

  7. 在CentOS 7 MySQL / MariaDB

    在CentOS7中,MariaDB  替代了MySQL;更多复杂的疑问可以在这里查看 MariaDB versus MySQL – Compatibility Install MySQL / Mari ...

  8. MATLAB实现矩阵分块相乘

    要实现一下功能,这里$\bf{x}_i$为行向量 $${\bf{A}} = \left[ \begin{array}{l}{{\bf{x}}_1}\\{{\bf{x}}_2}\end{array} \ ...

  9. 前端面试题之nina分享

    HTML相关 1.<!DOCTYPE>标签的定义与用法. <!DOCTYPE>的定义: <!DOCTYPE>声明位于文档中的最前面的位置,处于<html> ...

  10. git在公司内部的使用实践(转)

    从2011.10月左右,开始在后台组推行git版本控制,到现在也差不多半年了,也形成了一套基于git flow的副官模式工作流程: 版本定义: 版本号使用x.x.x进行定义,第一个x代表大版本只有在项 ...