java学习_多线程1

来源:互联网 发布:我的世界pe联机枪械js 编辑:程序博客网 时间:2024/05/16 07:17
1、线程和进程的概述

1.1、要想了解多线程,必须先了解线程,而要想了解线程,必须先了解进程,因为线程是依赖于进程而存在。 1.2、进程的概念 进程:就是正在运行的程序。进程是系统进行资源分配和调用的独立单位。每一个进程都有它自己的内存空间和系统资源。 1.3、多进程的意义 单进程的计算机只能做一件事情,而我们现在的计算机都可以做多件事情。 现在的计算机都是支持多进程的,可以在一个时间段内执行多个任务。可以提高CPU的使用率。 注意:进程不是同时进行的,是CPU在做着程序间的高效切换让我们觉得是同时进行的。 1.4、线程的概念 在同一个进程内又可以执行多个任务,而这每一个任务我就可以看出是一个线程。 线程:是程序的执行单元,执行路径。是程序使用CPU的最基本单位。 单线程:如果程序只有一条执行路径。 多线程:如果程序有多条执行路径。 1.5、多线程的意义
        多线程的存在,不是提高程序的执行速度。其实是为了提高应用程序的使用率。        程序的执行其实都是在抢CPU的资源,CPU的执行权。        多个进程是在抢这个资源,而其中的某一个进程如果执行路径比较多,就会有更高的几率抢到CPU的执行权。        我们是不敢保证哪一个线程能够在哪个时刻抢到,所以线程的执行有随机性。    1.6、并行和并发        前者是逻辑上同时发生,指在某一个时间内同时运行多个程序。        后者是物理上同时发生,指在某一个时间点同时运行多个程序。    1.7、Java的运行原理        由java命令启动JVM,JVM启动就相当于启动了一个进程。接着有该进程创建了一个主线程去调用main方法。

1.8、 思考题:  jvm虚拟机的启动是单线程的还是多线程的?

多线程的。原因是垃圾回收线程也要先启动,否则很容易会出现内存溢出。现在的垃圾回收线程加上前面的主线程, 最低启动了两个线程,所以jvm的启动其实是多线程的。


2、多线程的方式
    2.1多线程方式1:继承Thread类。

    2.1.1步骤

        A:自定义类MyThread继承Thread类。
        B:MyThread类里面重写run()?
            为什么是run()方法呢?
            不是类中的所有代码都需要被线程执行的。而这个时候,为了区分哪些代码能够被线程执行,
            java提供了Thread类中的run()用来包含那些被线程执行的代码。
        C:创建对象
        D:启动线程

public static void main(String[] args) {// 创建两个线程对象MyThread my1 = new MyThread();MyThread my2 = new MyThread();my1.start();my2.start();}}@Overridepublic void run() {for (int x = 0; x < 200; x++) {System.out.println(x);}}}


2.1.2获取和设置线程对象名称方法:

/* * 如何获取线程对象的名称呢? * public final String getName():获取线程的名称。 * 如何设置线程对象的名称呢? * public final void setName(String name):设置线程的名称 *  * 针对不是Thread类的子类中如何获取线程对象名称呢? * public static Thread currentThread():返回当前正在执行的线程对象 * Thread.currentThread().getName() */public class MyThreadDemo {public static void main(String[] args) {// 创建线程对象//带参构造方法给线程起名字MyThread my1 = new MyThread("young");MyThread my2 = new MyThread("long");my1.start();my2.start();//我要获取main方法所在的线程对象的名称,该怎么办呢?//遇到这种情况,Thread类提供了一个很好玩的方法://public static Thread currentThread():返回当前正在执行的线程对象System.out.println(Thread.currentThread().getName());}}

2.1.3 run()和start()的区别?

run():仅仅是封装被线程执行的代码,直接调用是普通方法

start():首先启动了线程,然后再由jvm去调用该线程的run()方法。

2.2 多线程方式2:实现Runnable接口

2.2.1步骤:

A:自定义类MyRunnable实现Runnable接口

B:重写run()方法

C:创建MyRunnable类的对象

D:创建Thread类的对象,并把C步骤的对象作为构造参数传递

2.2.2 示例

public class MyRunnableDemo {public static void main(String[] args) {// 创建MyRunnable类的对象MyRunnable my = new MyRunnable();// 创建Thread类的对象,并把C步骤的对象作为构造参数传递// Thread(Runnable target, String name)Thread t1 = new Thread(my, "young");Thread t2 = new Thread(my, "long");t1.start();t2.start();}}public class MyRunnable implements Runnable {@Overridepublic void run() {for (int x = 0; x < 100; x++) {// 由于实现接口的方式就不能直接使用Thread类的方法了,但是可以间接的使用System.out.println(Thread.currentThread().getName() + ":" + x);}}}

方式2实现接口方式的好处:

1)可以避免由于Java单继承带来的局限性。

2)适合多个相同程序的代码去处理同一个资源的情况,把线程同程序的代码,数据有效分离,较好的体现了面向对象的设计思想。

3、线程调度

1)分时调度模型   

所有线程轮流使用 CPU 的使用权,平均分配每个线程占用 CPU 的时间片

2)抢占式调度模型   

优先让优先级高的线程使用 CPU,如果线程的优先级相同,那么会随机选择一个,优先级高的线程获取的 CPU 时间片相对多一些。

Java使用的是抢占式调度模型。

publicfinal int getPriority():返回线程对象的优先级

publicfinal void setPriority(int newPriority):更改线程的优先级。

注意:

线程默认优先级是5。

线程优先级的范围是:1-10。

线程优先级高仅仅表示线程获取的 CPU时间片的几率高,但是要在次数比较多,或者多次运行的时候才能看到比较好的效果。

4、线程控制

线程休眠

public static void sleep(long millis)

线程加入

public final void join()

线程礼让

public static void yield()

后台线程

public final void setDaemon(boolean on)

中断线程

public final void stop()

public void interrupt()

5、多线程的应用电影院售票:

/* * 某电影院目前正在上映贺岁大片共有100张票,而它有3个售票窗口售票,* 请设计一个程序模拟该电影院售票。 */public class SellTicketDemo {public static void main(String[] args) {// 创建资源对象SellTicket st = new SellTicket();// 创建三个线程对象Thread t1 = new Thread(st, "窗口1");Thread t2 = new Thread(st, "窗口2");Thread t3 = new Thread(st, "窗口3");// 启动线程t1.start();t2.start();t3.start();}}public class SellTicket implements Runnable {// 定义100张票private int tickets = 100;//创建锁对象private Object obj = new Object();@Overridepublic void run() {while (true) {synchronized (obj) {if (tickets > 0) {try {Thread.sleep(100);} catch (InterruptedException e) {e.printStackTrace();}System.out.println(Thread.currentThread().getName()+ "正在出售第" + (tickets--) + "张票");}}}}}

6、线程安全问题

多线程可能会有一些问题,要想解决问题,就要知道哪些原因会导致出问题:

A:是否是多线程环境

B:是否有共享数据

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

思想:把多条语句操作共享数据的代码给包成一个整体,让某个线程在执行的时候,别人不能来执行。

问题是我们不知道怎么包啊?其实我也不知道,但是Java给我们提供了:同步机制。

同步代码块:

synchronized(对象){

需要同步的代码;

}

同步前提:多个线程

解决问题的时候要注意:多个线程使用的是同一个锁对象

同步的好处:同步的出现解决了多线程的安全问题。

同步的弊端:当线程相当多时,因为每个线程都会去判断同步上的锁,这是很耗费资源的,无形中会降低程序的运行效率。

0 0
原创粉丝点击