1:多线程(理解)

(1)如果一个应用程序有多条执行路径,则被称为多线程程序。

进程:正在执行的程序。

线程:程序的执行路径,执行单元。

单线程:如果一个应用程序只有一条执行路径,则被称为单线程程序。

多线程:如果一个应用程序有多条执行路径,则被称为多线程程序。

举例:迅雷下载,360的管理界面。

单进程单线程:一个人点一桌菜

单进程多线程:多个人点一桌菜

多进程多线程:多个人点多桌菜

(2)多线程程序实现的两种方案:(掌握 步骤我们一起写,代码你写)

A:继承Thread类

a:自定义类MyThread继承Thread类。

b:重写run方法(),在这里面输出1-100的数据。

c:创建测试类MyThreadTest,在测试类中创建MyThread类的多个对象。

d:调用start() ,注意不是run()方法,此外线程开启必须在main方法中代码之前,因为main方法也是一个线程,里面的代码是顺序执行的。

代码体现:

     public class MyThread extends Thread {

              public MyThread(){}

              public MyThread(String name) {

                  super(name);

              }

              public void run() {

                  for(int x=1; x<=100; x++) {

                     System.out.println(getName()+"---"+x);

                  }

              }

           }

           public class MyThreadTest {

              public static void main(String[] args) {

                  MyThread my1 = new MyThread("三国志");

                  MyThread my2 = new MyThread("三国杀");

                  //my1.setName("三国志");

                  //my2.setName("三国杀");

                  my1.start(); // 注意,调用的是start()方法,而不是run方法

                  my2.start();

              }

           }

B:实现Runnable接口(更好)

a:自定义类MyRunnable实现Runnable接口。

b:重写run方法(),在这里面输出1-100的数据。

c:创建测试类MyThreadTest,在测试类中创建MyRunnable类的一个对象。

d:在测试类创建Thread类的多个对象,并把MyRunnable类的一个对象作为构造参数传递。

用到的构造器:public Thread(Runnable target,

String name)

e:调用start()

代码体现:

 public class MyRunnable implements Runnable {

              public void run() {

                  for(int x=1; x<=100; x++) {

                     System.out.println(Thread.currentThread().getName()+"---"+x);

                  }

              }

           }

           public class MyRunnableTest {

              public static void main(String[] args) {

                  MyRunnable my = new MyRunnable();

                  Thread t1 = new Thread(my,"斗地主");

                  Thread t2 = new Thread(my,"三国群英传2");

                  t1.start();

                  t2.start();

              }

           }

(3)面试题:

A:如何启动一个线程

B:start()和run()方法的区别

C:线程随机性原理

D:线程的生命周期

E:线程的安全问题是怎么产生的,以及是如何解决的?

F:同步解决线程安全问题的方式有几种?

G:同步代码块的锁对象是谁?同步方法的锁对象是谁?

F:静态方法的锁对象是谁?

(4)几个方法

A、优先级(priority)

线程优先级代表了抢占CPU的能力。优先级越高,抢到CPU执行的可能性越大。(一般环境下效果不明显,优先级并非绝对的执行顺序。)

优先级相关方法:

public final void setPriority(int?newPriority) 优先级取值:1-10

public final int getPriority()

例子:cn.itcast2.demo

package cn.itcast2;
/*
* 线程优先级:
* public final int getPriority()获取优先级
* public final void setPriority(int newPriority)更改优先级
*/
public class Demo { public static void main(String[] args) { MyThread mt = new MyThread();
mt.setName("唐嫣");
// mt.setPriority(10);
System.out.println(mt.getPriority()); MyThread mt2 = new MyThread();
mt2.setName("柳岩");
mt2.setPriority(1); mt.start();
mt2.start();
} }
package cn.itcast2;

public class MyThread extends Thread {

    @Override
public void run() { for (int i = 0; i < 100; i++) {
System.out.println(getName()+":"+i);
}
}
}

B、暂停(yield)

暂停当前正在执行的线程对象,并执行其他线程。(效果不明显,如果想保证完成线程相互等待一次执行,需要使用到后边的等待唤醒机制 )

线程礼让相关方法:

public static void yield()

例子:cn.itcast2.demo4   cn.itcast2.MyThread1.java

package cn.itcast2;
/*
* 线程礼让:
* 暂停当前正在执行的线程对象,并执行其他线程
* public static void yield()
*/
public class Demo4 { public static void main(String[] args) { MyThread1 myThread = new MyThread1();
myThread.setName("唐嫣");
MyThread1 myThread2 = new MyThread1();
myThread2.setName("高圆圆"); myThread.start();
myThread2.start();
} }
package cn.itcast2;

public class MyThread1 extends Thread {

    @Override
public void run() {
for (int i = 0; i < 100; i++) {
System.out.println(getName()+":"+i);
Thread.yield();
}
}
}

C、加入(join) cn.itcast2.demo3

等待该线程终止。 即当前线程等待调用join方法的线程执行结束后再执行

public final void join() throws InterruptedException

package cn.itcast2;
/*
* 加入线程:
* public final void join()
throws InterruptedException 等待该线程终止。 即当前线程等待调用join方法的线程执行结束后再执行
*/
public class Demo3 { public static void main(String[] args) throws Exception { MyThread myThread = new MyThread();
myThread.setName("唐嫣");
MyThread myThread2 = new MyThread();
myThread2.setName("高圆圆"); myThread.setPriority(1); myThread.start(); myThread2.start();
myThread2.join(); //等待myThread2线程执行完以后,main方法所在的线程才会执行 for (int i = 0; i < 100; i++) {
System.out.println(Thread.currentThread().getName()+":"+i);
}
} }
package cn.itcast2;

public class MyThread extends Thread {

    @Override
public void run() { for (int i = 0; i < 100; i++) {
System.out.println(getName()+":"+i);
}
}
}

D、守护线程

设置守护线程的方法:

没有设置为守护线程的线程执行完毕,则程序停止运行

public final void setDaemon(boolean on)

注意:该方法必须在线程启动前调用

例子: cn.itcast2.demo5

package cn.itcast2;
/*
* 守护线程:
* 设置守护线程的方法:
* public final void setDaemon(boolean on)
* 注意:该方法必须在线程启动前调用
*/
public class Demo5 { public static void main(String[] args) { MyThread1 myThread = new MyThread1();
myThread.setName("唐嫣");
MyThread1 myThread2 = new MyThread1();
myThread2.setName("高圆圆"); myThread.setDaemon(true); //设置守护线程
myThread2.setDaemon(true);//设置守护线程 myThread.start();
myThread2.start(); for (int i = 0; i < 10; i++) { //主线程没有设置为守护线程,主线程执行完毕,则程序停止运行
System.out.println(Thread.currentThread().getName()+":"+i);
}
} }
package cn.itcast2;

public class MyThread1 extends Thread {

    @Override
public void run() {
for (int i = 0; i < 100; i++) {
System.out.println(getName()+":"+i);
Thread.yield();
}
}
}

E、线程睡眠(sleep)

指定线程休眠一定时间,进入等待状态。在该段时间结束后,线程重新可执行。

线程休眠相关方法:

public static void sleep(long?millis) throws InterruptedException

  例子:cn.itcast2.demo2

package cn.itcast2;
/*
* 线程休眠:
* public static void sleep(long millis) throws InterruptedException 将当前线程休眠,指定毫秒值
*/
public class Demo2 { public static void main(String[] args) throws Exception { System.out.println("我困了"); MyThread mt = new MyThread();
mt.start(); Thread.sleep(3000l);
System.out.println("我醒了"); } }
package cn.itcast2;

public class MyThread extends Thread {

    @Override
public void run() { for (int i = 0; i < 100; i++) {
System.out.println(getName()+":"+i);
}
}
}

F、线程中断(interrupt)

中断线程。

stop方法已过时,通常使用interrupt方法。

中断线程相关方法:

public void interrupt()   被中断的线程会报被中断异常,这时需要使用try/catch语句解决相关问题,线程后代码仍然可以继续执行

public final void stop()  (已过时)  直接停止线程,线程后代码无法被执行

     例子:cn.itcast2.demo6   cn.itcast2.MyThread2

package cn.itcast2;
/*
* stop方法直接停止线程,方法过于暴力。直接导致sleep后的代码无法执行。
* 线程中断:
* public void interrupt() 抛出异常,处理异常,后边代码继续执行
*/
public class Demo6 { public static void main(String[] args) throws Exception { MyThread2 myThread = new MyThread2();
MyThread2 myThread2 = new MyThread2(); myThread.start();
myThread2.start(); Thread.sleep(3000);
myThread.stop();
myThread2.interrupt();
} }
package cn.itcast2;

public class MyThread2 extends Thread {

    @Override
public void run() { System.out.println("我困了");
try {
Thread.sleep(10000l);
} catch (InterruptedException e) {
System.out.println("谁把我叫醒了,真烦!");
} System.out.println("睡醒了");
} }

(5)案例:

卖票案例。例子:cn.itcast3.demo  cn.itcast3.Ticket

package cn.itcast3;
/*
* 线程安全问题:
* 多个窗口卖指定个数的票
* 3个窗口卖100张票
* 票:共享数据
* 窗口:线程
*/
public class Demo { public static void main(String[] args) { Ticket ticket = new Ticket(); Thread thread = new Thread(ticket,"唐嫣");
Thread thread2 = new Thread(ticket,"柳岩");
Thread thread3 = new Thread(ticket,"高圆圆"); thread.start();
thread2.start();
thread3.start();
} }
package cn.itcast3;
/*
* 票类(线程执行的目标):执行买票动作
*/
public class Ticket implements Runnable { int number = 100; //应该放在成员变量的位置,实现三个对象的数据共享
Object o = new Object(); @Override
public void run() { while(true) {
synchronized(o) { try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
} //如果有票,就卖票
if(number>0) {
//卖票
System.out.println(Thread.currentThread().getName()+":"+number);
number--;
}
}
}
}
}

线程安全问题:

怎么产生的:

A:多线程环境

B:有共享数据

C:多条语句操作共享数据

怎么解决:

把C步骤给锁起来。

两种方案:

a:同步代码块

synchronized(锁对象) {

一个原子性操作

}

注意:几个线程需要使用相同的锁对象进行同步操作,使用不同的锁是无法完成同步操作的。

例子:cn.itcast3.demo  cn.itcast3.Ticket

package cn.itcast3;
/*
* 线程安全问题:
* 多个窗口卖指定个数的票
* 3个窗口卖100张票
* 票:共享数据
* 窗口:线程
*/
public class Demo { public static void main(String[] args) { Ticket ticket = new Ticket(); Thread thread = new Thread(ticket,"唐嫣");
Thread thread2 = new Thread(ticket,"柳岩");
Thread thread3 = new Thread(ticket,"高圆圆"); thread.start();
thread2.start();
thread3.start();
} }
package cn.itcast3;
/*
* 票类(线程执行的目标):执行买票动作
*/
public class Ticket implements Runnable { int number = 100; //应该放在成员变量的位置,实现三个对象的数据共享
Object o = new Object(); @Override
public void run() { while(true) {
synchronized(o) { try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
} //如果有票,就卖票
if(number>0) {
//卖票
System.out.println(Thread.currentThread().getName()+":"+number);
number--;
}
}
}
}
}

b:同步方法

把synchronized添加到方法声明上。返回值前。例如:public synchronized void method() {}

例子:cn.itcast4.demo  cn.itcast4.Ticket

package cn.itcast4;
/*
* 线程安全问题:
* 多个窗口卖指定个数的票
* 3个窗口卖100张票
* 票:共享数据
* 窗口:线程
*/
public class Demo { public static void main(String[] args) { Ticket ticket = new Ticket(); Thread thread = new Thread(ticket,"唐嫣");
Thread thread2 = new Thread(ticket,"柳岩");
Thread thread3 = new Thread(ticket,"高圆圆"); thread.start();
thread2.start();
thread3.start();
} }
package cn.itcast4;
/*
* 票类(线程执行的目标):执行买票动作
*
* 同步方法:
* 在方法上,返回值前,声明synchronized定义同步方法。
* 该方法的锁为所在对象。
*/
public class Ticket implements Runnable { int number = 100;
Object o = new Object(); @Override
public void run() { while(true) {
if(number%2==0) { //当票数为偶数时
synchronized(this) { //当前不变的对象,即ticket try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
} //如果有票,就卖票
if(number>0) {
//卖票
System.out.println(Thread.currentThread().getName()+":"+number);
number--;
}
}
}else {
method();
}
}
} public synchronized void method() { //在方法上,返回值前,声明synchronized定义同步方法。
//该方法的锁为所在对象。
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
} //如果有票,就卖票
if(number>0) {
//卖票
System.out.println(Thread.currentThread().getName()+":"+number);
number--;
}
}
}

c.静态同步方法

将方法所在类作为默认所,即XX.class

例子:cn.itcast5.demo  cn.itcast5.Ticket

package cn.itcast5;
/*
* 线程安全问题:
* 多个窗口卖指定个数的票
* 3个窗口卖100张票
* 票:共享数据
* 窗口:线程
*/
public class Demo { public static void main(String[] args) { Ticket ticket = new Ticket(); Thread thread = new Thread(ticket,"唐嫣");
Thread thread2 = new Thread(ticket,"柳岩");
Thread thread3 = new Thread(ticket,"高圆圆"); thread.start();
thread2.start();
thread3.start();
} }
package cn.itcast5;
/*
* 票类(线程执行的目标):执行买票动作
*
* 静态同步方法:
* 在方法上,返回值前,声明static synchronized定义静态同步方法。
* 该方法的锁为所在的类对象。
*/
public class Ticket implements Runnable { static int number = 100;
Object o = new Object(); @Override
public void run() { while(true) {
if(number%2==0) {
synchronized(Ticket.class) { //类对像 try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
} //如果有票,就卖票
if(number>0) {
//卖票
System.out.println(Thread.currentThread().getName()+":"+number);
number--;
}
}
}else {
method();
}
}
} public static synchronized void method() { //类对像 try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
} //如果有票,就卖票
if(number>0) {
//卖票
System.out.println(Thread.currentThread().getName()+":"+number);
number--;
}
}
}

(6)Java同步机制的优缺点:

a:优点:解决了多线程安全问题

b:缺点:当线程相当多时,因为每个线程都会去判断同步上的锁,这是很耗费资源的,无形中会降低程序的运行效率。对于一个简单操作,单线程速度更快。

(7)多线程的优缺点

多线程并不提高某个程序的执行速度,仅仅是提高了CPU的使用率。

图1:多线程示意图

图2:多线程现率高

图3:多线程状态图

2:单例设计模式(理解 面试)

(1)保证类在内存中只有一个对象。

(2)怎么保证:

A:构造私有

B:自己造一个对象

C:提供公共访问方式

(3)两种方式:

A:懒汉式(面试)

public class Student {

private Student(){}

private static Student s = null;

public synchronized static Student getStudent() {

if(s == null) {

s = new Student();

}

return s;

}

}

B:饿汉式(开发)

public class Student {

private Student(){}

private static Student s = new Student();

public static Student getStudent() {

return s;

}

}

(4)JDK的一个类本身也是单例模式的。

Runtime

多线程的实现及常用方法_DAY23的更多相关文章

  1. java 多线程:Thread类常用方法:setPriority优先级、interrupt中断标记、suspend暂停与唤醒resume(已过时);daemon守护线程

    常用方法: boolean isAlive() 测试此线程是否存活. boolean isDaemon() 测试此线程是否为守护程序线程. static void sleep?(long millis ...

  2. 08-Java 多线程编程

    1.Java多线程-线程与进程的区别 (1)线程:程序中单独依靠程序进行运行 线程是程序中的顺序控制流,只能使用分配给程序的资源和环境. (2)进程:执行中的程序 一个进程可以包含一个或多个线程. 一 ...

  3. [Java] 转:多线程 (并发)总结

    一概念 二创建多线程方法 三线程常用方法不完整可以自己查阅JDK文档 四线程的生命周期与转换 五同步 六竞争者消费者 七线程池 八JDK 线程工具 线程基础: 1. 创建 2. 状态切换 3. sle ...

  4. Java 多线程 (并发)总结

    一.概念 1. 维基百科解释 进程是什么? http://zh.wikipedia.org/wiki/%E8%BF%9B%E7%A8%8B 线程是什么? http://zh.wikipedia.org ...

  5. 搞定python多线程和多进程

    1 概念梳理: 1.1 线程 1.1.1 什么是线程 线程是操作系统能够进行运算调度的最小单位.它被包含在进程之中,是进程中的实际运作单位.一条线程指的是进程中一个单一顺序的控制流,一个进程中可以并发 ...

  6. python多线程和多进程

    1 概念梳理: 1.1 线程 1.1.1 什么是线程 线程是操作系统能够进行运算调度的最小单位.它被包含在进程之中,是进程中的实际运作单位.一条线程指的是进程中一个单一顺序的控制流,一个进程中可以并发 ...

  7. python 多线程示例

    原文链接:http://www.cnblogs.com/whatisfantasy/p/6440585.html 1 概念梳理: 1.1 线程 1.1.1 什么是线程 线程是操作系统能够进行运算调度的 ...

  8. 原创Java多线程详解(一)

    只看书不实践是不行的.来实践一下~~~~~~(引用请指明来源) 先看看百科对多线程的介绍 多线程(英语:multithreading),是指从软件或者硬件上实现多个线程并发执行的技术.具有多线程能力的 ...

  9. JAVAOOP多线程

    进程每个独立运行的任务对应一个进程,每个进程可以产生多个线程 特点:1,进程是系统运行程序的基本单位 2,每一个进程都有自己独立的一块内存空间,一组系统资源 3,每一个进程的内部数据和状态都是完全独立 ...

随机推荐

  1. IntelliJ IDEA 2017版 spring-boot2.0.4的yml配置使用

    一.必须配置字端两个 server: port: 8080 servlet: context-path: /demo 二.两种mvc转换springboot,一种是注解,一种就是.yml或proper ...

  2. 微信 公众号平台 与 开放平台 获取用户信息 scope snsapi_login

    微信公众号(公众平台) 和 微信开放平台 是两码事.公众号(公众平台)获取的scope只包括两种:snsapi_base 和snsapi_userinfo,前者是静默获取,用户无感知:后者是需要用户确 ...

  3. 学以致用十六-----Centos7.2编译安装mysql5.6.22

    一.系统环境 二.卸载系统自带的mariadb rpm -qa | grep db rpm -e --nodeps mariadb-libs-5.5.60 rpm -e --nodeps mariad ...

  4. ==和equals的比较

    一 : == 的特点: a == b ; 1.如果A和B是基本数据类型    ==   比较的是两个变量的值 2.如果A和B是引用数据类型    == 比较的是两个变量的内存地址 二:重写的equal ...

  5. 11-border(边框)

    边框 border:边框的意思,描述盒子的边框 边框有三个要素: 粗细 线性样式 颜色 border: solid 如果颜色不写,默认是黑色.如果粗细不写,不显示边框.如果只写线性样式,默认的有上下左 ...

  6. Qt_简介

    Qt简介: 1990 开发 1991 发布Qt 1.0. 公司:Trolltech (奇趣科技) 1997 Qt被用来开发Linux桌面KDE 2008 被Nokia收购 2012 被转让给Digia ...

  7. mach_absolute_time 使用

    今天看荣哥时间常用函数封装里有个不常见的函数 ,mach_absolute_time() ,经查询后感觉是个不错的函数,网上关于这个函数搜索以后简单整理来一下. 什么事Mach? 时间例程依赖于所需要 ...

  8. output.php

    <?php /** * */ class Output { function __construct() { $this->_zlib_oc = @ini_get('zlib.output ...

  9. JS 对象(Object)和字符串(String)互转方法

    利用原生JSON对象,将对象转为字符串 1 2 3 4 5 6 var jsObj = {}; jsObj.testArray = [1,2,3,4,5]; jsObj.name = 'CSS3'; ...

  10. python操作Hbase

    本地操作 启动thrift服务:./bin/hbase-daemon.sh start thrift hbase模块产生: 下载thrfit源码包:thrift-0.8.0.tar.gz 解压安装 . ...