12-23java面向对象之多线程

1.多线程的概念

几乎所有的操作系统都支持同时运行多个任务,每一个任务通常就是一个程序,每个运行的程序就是一个进程。当一个程序运行是,内部可能包含了多个顺序执行流,每个执行流就是线程。

继承的特点:并发性。多个进程可以在单个处理器上并发执行,不会相互影响,

2.java多线程的实现

2.1继承Thread类

在java.lang包中定义了Thread类,继承该类之后,必须覆写run()方法.

启动该线程,必须调用Thread类中的start()方法,但是该方法最终还是调用的run()方法。

class MyThread extends Thread		// 继承Thread类
{
	private String name ;
	public MyThread(String name)	// 构造方法
	{
		this.name = name ;
	}
	public void run()				// 覆写run方法
	{
		for (int i =0;i<10 ;++i )
		{
			System.out.println(this.name + "运行,i=" + i);
		}
	}
}
public class TestThread1
{
	public static void main(String[] args)
	{
		MyThread mt1 = new MyThread("线程1") ;
		MyThread mt2 = new MyThread("线程2") ;
		mt1.run();
		mt2.run();
	}
}

运行结果发现:并没有并发执行效果,所以要修改程序。必须使用start()方法来启动线程。

class MyThread extends Thread		// 继承Thread类
{
	private String name ;
	public MyThread(String name)	// 构造方法
	{
		this.name = name ;
	}
	public void run()				// 覆写run方法
	{
		for (int i =0;i<10 ;++i )
		{
			System.out.println(this.name + "运行,i=" + i);
		}
	}
}
public class TestThread2
{
	public static void main(String[] args)
	{
		MyThread mt1 = new MyThread("线程1") ;		// 创建对象
		MyThread mt2 = new MyThread("线程2") ;
		mt1.start();
		mt2.start();
	}
}

程序运行总是并发执行不同的线程。那个线程先抢占到CPU资源就执行它。

如果线程已经启用了,再次调用start方法会出现异常。

class MyThread extends Thread		// 继承Thread类
{
	private String name ;
	public MyThread(String name)	// 构造方法
	{
		this.name = name ;
	}
	public void run()				// 覆写run方法
	{
		for (int i =0;i<10 ;++i )
		{
			System.out.println(this.name + "运行,i=" + i);
		}
	}
}
public class TestThread3
{
	public static void main(String[] args)
	{
		MyThread mt1 = new MyThread("线程1") ;		// 创建对象
		mt1.start();
		mt1.start();
	}
}

提示错误信息;


Exception in thread "main" java.lang.IllegalThreadStateException

at java.lang.Thread.start(Unknown Source)

at TestThread3.main(TestThread3.java:22)

2.2实现Runnable接口

Runnable接口中只定义了run()方法,所以也需要覆写该方法。它之中并没有start()方法,但是在Thread的构造方法中有这么一个接收Runnable实例的,用他作为启动线程的操作。

Thread
public Thread(Runnable target)

class MyThread implements Runnable		// 继承Thread类
{
	private String name ;
	public MyThread(String name)	// 构造方法
	{
		this.name = name ;
	}
	public void run()				// 覆写run方法
	{
		for (int i =0;i<10 ;++i )
		{
			System.out.println(this.name + "运行,i=" + i);
		}
	}
}
public class TestThread4
{
	public static void main(String[] args)
	{
		Runnable r1 = new MyThread("线程1") ;		// 向上转换实现接口
		Runnable r2 = new MyThread("线程2") ;		// 向上转换实现接口
		Thread mt1 = new Thread(r1);
		Thread mt2 = new Thread(r2);
		mt1.start();
		mt2.start();
	}
}

执行结果:完成了多线程的功能。

2.3联系与区别

联系:定一个是Thread也是Runnable的实现,这个就是之前的代理设计。


All Implemented Interfaces:   Runnable

区别:使用Thread操作多线程无法实现资源的共享,而Runnable可以共享。同时Thread只能实现单继承,接口可以多继承,推荐使用Runnable。

使用Runnable优点:

1、适合多个相同程序代码的多线程处理同一个资源

2、避免单继承

3、增强健壮性

下面验证共享;

//本程序验证共享属性
class MyThread extends Thread
{
	private int ticket = 5;			// 定义属性有5个
	public void run()				// 覆写run方法
	{
		for (int i =0;i<10 ;++i )
		{
			if (ticket > 0)
			{
				System.out.println("卖出门票ticket =" + ticket--);
			}
		}
	}
}
public class TestThread6
{
	public static void main(String[] args)
	{
		Thread mt1 = new MyThread();
		Thread mt2 = new MyThread();
		mt1.start();
		mt2.start();
	}
}

这个时候发现,每个线程都各卖个的,没有到达资源共享。

//本程序验证共享属性
class MyThread implements Runnable		// 实现Runnable接口
{
	private int ticket = 5;			// 定义属性有5个
	public void run()				// 覆写run方法
	{
		for (int i =0;i<10 ;++i )
		{
			if (ticket > 0)
			{
				System.out.println("卖出门票ticket =" + ticket--);
			}
		}
	}
}
public class TestThread5
{
	public static void main(String[] args)
	{
		Runnable r1 = new MyThread() ;		// 向上转换实现接口
		Thread mt1 = new Thread(r1);
		Thread mt2 = new Thread(r1);
		mt1.start();
		mt2.start();
	}
}

3.线程的状态

调用了start也不会立即启动,需要等待CPU。

4.线程的操作方法

对线程的操作都在Thread类中。

4.1取得和设置线程名称

在Thread类的构造方法中有一个名称的参数,同时具有方法setName()和getName()可以分别设置和获取名称。线程名称可以相同,在运行时候可以修改。

Public static Thead currentThread()方法返回当前的线程。

//本程序测试线程名称
class MyThread implements Runnable
{
	public void run()				// 覆写run方法
	{
		for (int i =0;i<10 ;++i )
		{
			System.out.println(Thread.currentThread().getName() +"当前线程名称是—"+ i);
		}
	}
}
public class TestThread7
{
	public static void main(String[] args)
	{
		Runnable mt1 = new MyThread();
		Runnable mt2 = new MyThread();
		Thread t1 = new Thread(mt1);			//系统自动命名
		Thread t2 = new Thread(mt2,"线程A");			//手动命名
		t1.start() ;
		t2.start();
	}
}

运行发现,线程设置名称之后会按照设置名称自动运行,没有设置名称的按照格式Thread-0 依次编号,实际上肯定存在static属性,用于记录产生对象的个数。

4.2取得当前线程


public static Thread currentThread()

Returns a reference to the currently executing thread object.

//本程序测试线程名称
class MyThread implements Runnable
{
	public void run()				// 覆写run方法
	{
		for (int i =0;i<10 ;++i )
		{
			System.out.println(Thread.currentThread().getName() +"当前线程名称是—"+ i);
		}
	}
}
public class TestThread8
{
	public static void main(String[] args)
	{
		Runnable mt2 = new MyThread();
		Thread t2 = new Thread(mt2,"线程A");			//手动命名
		t2.start();
		t2.run();
	}
}

此时程序中由主方法直接调用线程的run方法,此时main是由“t2.run();”产生的。

Java程序在启动的时候至少有两个线程。JVM运行的时候启动了一个线程,在资源管理器中能够看到,同时后台还有垃圾收集GC线程。

4.3判断线程是否在执行

public final boolean isAlive()
//本程序测试线程名称
class MyThread implements Runnable
{
	public void run()				// 覆写run方法
	{
		for (int i =0;i<3 ;++i )
		{
			System.out.println("当前线程名称是—"+Thread.currentThread().getName() + i);
		}
	}
}
public class TestThread9
{
	public static void main(String[] args)
	{
		Runnable mt2 = new MyThread();
		Thread t2 = new Thread(mt2,"线程A");			//手动命名
		System.out.println("线程启动之前->" + t2.isAlive());
		t2.start();
		System.out.println("线程启动之后->" + t2.isAlive());
		for (int i= 1;i<10 ;++i )
		{
			System.out.println(t2.isAlive());
		}
		System.out.println("代码执行之后->" + t2.isAlive());
	}
}

由于此时在线程A和主方法中执行次序不确定,所以结果不同。

4.4线程强制运行


public final void join()                throws InterruptedException

Waits for this thread to die.

//本程序测试线程名称
class MyThread implements Runnable
{
	public void run()				// 覆写run方法
	{
		for (int i =0;i<40 ;++i )
		{
			System.out.println("当前线程名称是—"+ Thread.currentThread().getName() + i);
		}
	}
}
public class TestThread10
{
	public static void main(String[] args)
	{
		Runnable mt1 = new MyThread();
		Thread t1 = new Thread(mt1,"线程A");			//手动命名
		t1.start();
		for (int i =0;i<40 ;++i )
		{
			if (i>10)
			{
				try
				{
					t1.join();
				}
				catch (InterruptedException e)
				{
				}
			}
			System.out.println("main运行" + i);
		}
	}
}

当main运行到10之后,都是由主线程占用。

4.5线程的休眠


public static void sleep(long millis)  使用类名称调用,类似current                  throws InterruptedException

//本程序测试线程名称
class MyThread implements Runnable
{
	public void run()				// 覆写run方法
	{
		for (int i =0;i<10 ;++i )
		{
			try
			{
				Thread.sleep(2000);			// 每2s产生一个输出
			}
			catch (InterruptedException e)
			{
			}
			System.out.println("当前线程名称是—"+ Thread.currentThread().getName() + i);
		}
	}
}
public class TestThread11
{
	public static void main(String[] args)
	{
		Runnable mt1 = new MyThread();
		Thread t1 = new Thread(mt1,"线程A");			//手动命名
		t1.start();
	}
}

4.6线程强制中断

当一个线程正在运行时,另一个线程可以使用interrupt方法中断其运行。


public void interrupt()

Interrupts this thread.

//本程序测试线程名称
class MyThread implements Runnable
{
	public void run()				// 覆写run方法
	{
		System.out.println("1.进入run方法");
		try
		{
			Thread.sleep(5000);			// 休眠5s
			System.out.println("2.休眠结束");
		}
		catch (InterruptedException e)
		{
			System.out.println("3.休眠中断");
			return ;		// 返回调用处
		}
		System.out.println("4.run正常结束");
	}
}
public class TestThread12
{
	public static void main(String[] args)
	{
		Runnable mt1 = new MyThread();
		Thread t1 = new Thread(mt1,"线程A");			//手动命名
		t1.start();
		try  //作用是延时
		{
			Thread.sleep(2000);
		}
		catch (InterruptedException e)
		{}
		t1.interrupt();
	}
}

4.7后台线程

一个线程在运行,整个java进程不会消失。可以设置后台线程,哪怕进程结束了,线程还在。


public final void setDaemon(boolean on)

class MyThread implements Runnable
{
	public void run()				// 覆写run方法
	{
		while (true)
		{
			System.out.println(Thread.currentThread().getName() + "在运行");
		}
	}
}
public class TestThread13
{
	public static void main(String[] args)
	{
		Runnable mt1 = new MyThread();
		Thread t1 = new Thread(mt1,"线程A");			//手动命名
		t1.start();
		t1.setDaemon(true);
	}
}

4.8优先级设置


public final void setPriority(int newPriority)

Changes the priority of this thread.

<p>注意:主方法的优先级是<span style="font-family:Times New Roman;">5</span></p><h2>4.9<span style="font-family:黑体;">线程的礼让</span></h2><table><tbody><tr><td valign="top"><p>public static void yield()</p><p>Causes the currently executing thread object to temporarily pause and allow other threads to execute.</p></td></tr></tbody></table>class MyThread implements Runnable
{
	public void run()				// 覆写run方法
	{
		for (int i=0;i<3 ;++i )
		{
			try
			{
				Thread.sleep(1000);
				System.out.println("正在运行的是: " + Thread.currentThread().getName() + i);
			}
		catch (InterruptedException e){}
		}
	}
}
public class TestThread14
{
	public static void main(String[] args)
	{
		Runnable mt1 = new MyThread();
		Thread t1 = new Thread(mt1,"线程A");			//手动命名
		Runnable mt2 = new MyThread();
		Thread t2 = new Thread(mt2,"线程B");			//手动命名
		Runnable mt3 = new MyThread();
		Thread t3 = new Thread(mt3,"线程C");			//手动命名
		t1.setPriority(Thread.MAX_PRIORITY);							//设置优先级
		t2.setPriority(Thread.MIN_PRIORITY);
		t3.setPriority(Thread.NORM_PRIORITY);
		t1.start();
		t2.start();
		t3.start();
	}
}

注意:主方法的优先级是5

4.9线程的礼让


public static void yield()

Causes the currently executing thread object to temporarily pause and allow other threads to execute.

class MyThread implements Runnable
{
	public void run()				// 覆写run方法
	{
		for (int i=0;i<5 ;++i )
		{
			System.out.println("正在运行的是: " + Thread.currentThread().getName() + i);
			if (i ==3)
			{
				System.out.println("线程礼让");
				Thread.currentThread().yield();
			}
		}
	}
}
public class TestThread15
{
	public static void main(String[] args)
	{
		Runnable mt1 = new MyThread();
		Thread t1 = new Thread(mt1,"线程A");			//手动命名
		Runnable mt2 = new MyThread();
		Thread t2 = new Thread(mt2,"线程B");			//手动命名
		t1.start();
		t2.start();
	}
}

祝大家健健康康,快快乐乐。

时间: 2024-08-07 01:47:34

12-23java面向对象之多线程的相关文章

第12天 面向对象

第12天面向对象 今日内容介绍 构造方法 this super 构造方法 我们对封装已经有了基本的了解,接下来我们来看一个新的问题,依然以Person为例,由于Person中的属性都被private了,外界无法直接访问属性,必须对外提供相应的set和get方法.当创建人对象的时候,人对象一创建就要明确其姓名和年龄,那该怎么做呢? 构造方法介绍 在开发中经常需要在创建对象的同时明确对象的属性值,比如员工入职公司就要明确他的姓名.年龄等属性信息. 那么,创建对象就要明确属性值,那怎么解决呢?也就是在

java笔记12之面向对象初始

1 概述 类:是一组相关的属性和行为的集合.是一个抽象的概念.     对象:是该类事物的具体表现形式.具体存在的个体. (1)面向对象思想     面向对象是基于面向过程的编程思想.        面向过程:强调的是每一个功能的步骤    面向对象:强调的是对象,然后由对象去调用功能     (2):面向对象的思想特点    A:是一种更符合我们思想习惯的思想    B:可以将复杂的事情简单化    C:将我们从执行者变成了指挥者            举例:        买电脑:     

关于指针、面向对象、多线程的概义

指针 在计算机科学中,指针(Pointer)是编程语言中的一个对象,利用地址,它的值直接指向(points to)存在电脑存储器中另一个地方的值.由于通过地址能找到所需的变量单元,可以说,地址指向该变量单元.因此,将地址形象化的称为“指针”.意思是通过它能找到以它为地址的内存单元.在高级语言中,指针有效地取代了在低级语言,如汇编语言与机器码,直接使用通用暂存器的地方,但它可能只适用于合法地址之中.指针参考了存储器中某个地址,通过被称为反参考指针的动作,可以取出在那个地址中存储的值.作个比喻,假设

2017/12/28-1集合和多线程

1.---|Collection: 单列集合 ---|List: 有存储顺序, 可重复 ---|ArrayList: 数组实现, 查找快, 增删慢 由于是数组实现, 在增和删的时候会牵扯到数组 增容, 以及拷贝元素. 所以慢.数组是可以直接 按索引查找, 所以查找时较快 ---|LinkedList: 链表实现, 增删快, 查找慢 由于链表实现, 增加时只要让前一个元素记住自 己就可以, 删除时让前一个元素记住后一个元 素, 后一个元素记住前一个元素. 这样的增删效 率较高但查询时需要一个一个的

12、面向对象的思想(OOP)

面向对象与面向过程 1.都是解决问题的思维方式,都是代码的组织的方式: 2.解决简单的问题可以使用面向过程: 3.解决复杂的问题建议使用面向对象,微观处理依旧会使用面向过程. 对象的进化史(数据管理的处理过程) 事物的发展总是遵循"量变引起质变"的哲学原则,在最初不需要对象. 1.数据无管理时代:变量,常量等数据量小: 2.数据管理时代(数组):同种类型数据: 3.对象管理时代:不同数据类型,同样可以具有方法: 原文地址:https://www.cnblogs.com/zglbt/p/

2019.12.17 面向对象习题

/** * TimeTraveler.java * com.DuiXiang * * Function: TODO * * ver date author * ────────────────────────────────── * 2019年12月17日 17671 * * Copyright (c) 2019, TNT All Rights Reserved.*/ package com.DuiXiang; /** * ClassName:TimeTraveler Function: TOD

12:面向对象三大特性(封装、继承、多态)之继承

本小节知识点: 继承基本概念 OC中的继承关系 OC中如何实现继承 1.继承基本概念 现实生活中的继承 交通工具类是一个基类(也称做父类),通常情况下所有交通工具所共同具备的特性,如速度与额定 载人的数量 按照生活常规,我们来继续给交通工具来细分类的时候,我们会分别想到有汽车类和飞机类等 等,汽车类和飞机类同样具备速度和额定载人数量这样的特性,而这些特性是所有交通工具所共有的,那么就可以让汽车或飞机类继承交通工具类,这样当建立汽车类和飞机类的时候我们无需再定义交通工具类(基类)中已经有的成员和方

2014年 12月15日 多线程编程

做了这么多年学渣,一直没好好去理解,这次得认真了,感恩网络的好资源. 进程就是一个运行中的程序,而线程就是一个进程运行的路径,一个进程至少有一个主线程.在ios系统中主线程负责ui更新.有三种方法管理: gcd. 程序员只需要管理队列和任务,不需要直接管理线程的分配和生命周期.程序员只需要把操作放入队列中即可,操作的执行是通过block语法 队列可以分为串行.并行.全局.主线程队列,任务分为同步.异步任务 串行队列,同步任务,不创建新线程,还由主线程执行 串行队列,异步任务,创建一个子线程, 并

Python学习笔记12(面向对象进阶)

银角大王这一篇知识点整理的特别的清晰明了,直接搬运了.给你们一个传送门地址http://www.cnblogs.com/wupeiqi/p/4766801.html 本篇将详细介绍Python 类的成员.成员修饰符.类的特殊成员. 一.类的成员 类的成员可以分为三大类:字段.方法和属性 注:所有成员中,只有普通字段的内容保存对象中,即:根据此类创建了多少对象,在内存中就有多少个普通字段.而其他的成员,则都是保存在类中,即:无论对象的多少,在内存中只创建一份. 一.字段 字段包括:普通字段和静态字