多线程基础

------- android培训java培训、期待与您交流! ----------

线程的概念

在操作系统中,可以通过多个进程并发的执行多个任务。进程是有代码、数据、内核状态和一组寄存器组成。一个包含多线程的进程也能够实现进程内多任务并发的执行。但线程不包含进程地址空间中的代码和数据,线程是计算过程在某一时刻的状态。所以,线程间的切换要比进程间的切换负担小得多。

进程是一个内核级的尸体,用户(程序)不能直接访问这些数据,而线程是用户级的尸体,线程结构保存在用户空间中,能够被普通的用户级函数直接访问。Java中的线程模型包括三个部分:一个虚拟的CPU,该CPU执行的代码和代码所操作的数据。

线程的创建

Thread

Java中的线程体是由线程类的run方法开始执行,就想Java Applicationmain()开始,Appletinit()开始一样。Thread类的构造方法有多个,一般结构可以表示如下:

public Thread(ThreadGroup group, Runnable target, String name)

group指明该线程所属的线程组.

target提供线程体的对象。Runnable接口中定义了run()方法,实现该接口的类可以提供线程体,线程启动时该对象的run()方法将被调用。

name线程的名称。每个线程有自己的名称,如果namenull, Java自动赋予一个唯一的名称

由于Thread类本身已经实现了Runnable接口,因此可以有两种方式提供run()方法的实现:实现Runnable接口和继承Thread类。

通过实现Runnable接口创建线程

public class ThreadTest {
	public static void main(String[] args) {
		Thread t1 = new Thread(new Hello());
		Thread t2 = new Thread(new Hello());
		t1.start();
		t2.start();
	}

}

class Hello implements Runnable{
	@Override
	public void run() {
		for(int i=0;i<5;i++){
			System.out.println("Hello"+i);
		}
	}
}

打印结果可能为:

Hello0
Hello0
Hello1
Hello2
Hello3
Hello4
Hello1
Hello2
Hello3
Hello4

一个线程是Thread类的一个实例,线程是从一个传递给线程的RunnableRunnable实例的run()方法开始执行。必须调用线程的start()方法才能启动线程。

通过继承Thread类创建线程

因为Thread类实现了Runnable接口,所以可以通过继承Thread类来创建线程:

Thread类派生子类,并重写其run方法来定义线程体

创建该子类的对象创建线程

public class ThreadTest2 {
	public static void main(String[] args) {
		Thread t1 = new Hello2();
		Thread t2 = new Hello2();
		t1.start();
		t2.start();
	}
}

class Hello2 extends Thread{
	@Override
	public void run() {
		for(int i=0;i<5;i++){
			System.out.println("Hello"+i);
		}
	}
}


创建线程的两种方法的比较

采用继承Thread类方法的优点:

程序代码简单,并可以在run()方法中直接调用线程的Thread类的其他方法。

实现Runnable接口的优点:

1. 符合面向对象设计的思想:从面向对象设计的角度看,Thread类是虚拟CPU的封装,所以Thread的子类应该封装CPU的行为,但在Thread子类中构建线程,子类大都是与CPU不相关的类。而实现Runnable接口,更加符合面向对象设计思想。

2. 便于继承其他类:实现了Runnable接口的类也可以继承其他类

可见一般通过实现Runnable接口创建线程的方法更值得提倡。

线程控制

下面是Thread类提供的一些基本线程的控制方法

1. sleep()

该方法能够把CPU让给优先级比其低的线程。该方法可以使一个线程暂停运行一端固 定的时间。在休眠时间内,线程将不运行。

2. yield()

调用该方法后,可以使其具有与当前线程相同优先级的线程有运行的机会。yield()方法 执行后,把该线程放入到可运行线程池中,并允许其他同优先级的可运行的线程运行。 如果没有同优先级的线程,该线程继续运行。

3. join()

t.join()方法使当前的线程等待直到线程t线程运行结束为止,当线程恢复到可运行状态。join()方法可以提供参数join(long millis)join(long millis, int nanos):参数表示当前线程将等待线程t结束或者最多等待给定时间后,在继续执行。如果没有参数则会等待t结束。

1. interrupt()

如果一个线程t在调用sleep()join()wait()等方法被阻塞时,则t.interrupt()方法中断t的阻塞状态,并且t将接收到InterruptException异常。

2. currentThread()

该静态方法返回当前线程的引用。

3. isAlive()

判断线程是否活着,返回true则表示线程已经启动但还没有运行结束。

4. stop()

强行终止线程,容易造成线程的不一致,不提倡使用。可以使用标志flag通知一个线程应该结束。

5. suspend()resume()

在一个线程中调用t.suspend(),将使另一个线程t暂停执行。要想恢复线程,必须由其他线程调用t.resume(),不提倡该方法,易造成死锁。

public class JoinTest {

	public static void main(String[] args) throws InterruptedException {
		Thread t = new Thread(new Hello());
		t.start();
		
		for(int i=0;i<5;i++){
			if(i==2 && t.isAlive()){
				System.out.println("Hello Thread joins");
				t.join();
			}
			System.out.println("main Thread "+i);
		}
	}

}

class Hello implements Runnable{
	@Override
	public void run() {
		for(int i=0;i<5;i++){
			System.out.println("Hello "+i);
		}
	}
}

打印结果如下:

main Thread 0
main Thread 1
Hello Thread joins
Hello 0
Hello 1
Hello 2
Hello 3
Hello 4
main Thread 2
main Thread 3
main Thread 4

本例测试join方法,主线程在调用t.join()之后将会等待直到t运行结束。

public class ThreadTest {
	public static void main(String[] args) {
		Hello2 r = new Hello2();
		Thread t = new Thread(r);
		t.setPriority(Thread.MAX_PRIORITY);
		t.start();
		
		
		System.out.println("Here to stop thread t");
		r.stopHello();
		for(int i=0;i<3;i++){
			System.out.println("main thread "+i);
		}
	}
}

class Hello2 implements Runnable{
	int i=0;
	private boolean timeToQuit = false;
	@Override
	public void run() {
		while(!timeToQuit){
			System.out.println("Hello "+i++);
			try{
				if(i%2 == 0){
					Thread.sleep(1);
				}
			}catch(Exception e){}
		}
	}
	
	public void stopHello(){
		timeToQuit = true;
	}
	
}

可能的打印结果:

Here to stop thread t
Hello 0
Hello 1
main thread 0
main thread 1
main thread 2

本例测试通过标志flag来停止一个线程。

线程同步

多线程多共享数据的操作时,由于线程运行顺序是不确定的,这会导致运行结果的不确定性,使共享数据的一致性被破坏,因此在某些应用程序中必须对线程的并发操作进行控制。 

class Hello3 implements Runnable {
	private int count = 5;

	public void run() {
		for (int i = 0; i < 10; ++i) {
			printCount();
		}
	}

	private synchronized void printCount() {
		if (count >= 0) {
			try {
				Thread.sleep(100);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
			System.out.println(count--);
		}
	}

	public static void main(String[] args) {
		Hello3 he = new Hello3();
		Thread h1 = new Thread(he, "t1");
		Thread h2 = new Thread(he, "t2");
		Thread h3 = new Thread(he, "t2");
		h1.start();
		h2.start();
		h3.start();
	}
}

一次可能的打印结果如下:
5
5
4
3
2
1
0
-1

显然几个线程对数据count进行了共享操作,run()方法可能并不会在某个线程执行过程中完全执行,这就造成了数据的不一致。为了保证数据的一致性,需要使用到同步技术,所谓同步就是某个数据在某一段时间内只被一个线程使用。采用同步,可以使用同步代码块和同步方法两种来完成。我们对代码做如下改动:

private void printCount() {
	synchronized (this) {
		if (count >= 0) {
			try {
				Thread.sleep(100);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
			System.out.println(count--);
		}
	}
}

或者

private synchronized void printCount() {
	if (count >= 0) {
		try {
			Thread.sleep(100);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		System.out.println(count--);
	}
}

这时候的打印结果为:

5
4
3
2
1

这样一来就实现了线程的同步,保证了线程对共享数据同步操作,保证了数据的一致性。

------- android培训java培训、期待与您交流! ----------

资源下载链接为: https://pan.quark.cn/s/5c50e6120579 在Android移动应用开发中,定位功能扮演着极为关键的角色,尤其是在提供导航、本地搜索等服务时,它能够帮助应用获取用户的位置信息。以“baiduGPS.rar”为例,这是一个基于百度地图API实现定位功能的示例项目,旨在展示如何在Android应用中集成百度地图的GPS定位服务。以下是对该技术的详细阐述。 百度地图API简介 百度地图API是由百度提供的系列开放接口,开发者可以利用这些接口将百度地图的功能集成到自己的应用中,涵盖地图展示、定位、路径规划等多个方面。借助它,开发者能够开发出满足不同业务需求的定制化地图应用。 Android定位方式 Android系统支持多种定位方式,包括GPS(全球定位系统)和网络定位(通过Wi-Fi及移动网络)。开发者可以根据应用的具体需求选择合适的定位方法。在本示例中,主要采用GPS实现高精度定位。 权限声明 在Android应用中使用定位功能前,必须在Manifest.xml文件中声明相关权限。例如,添加<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />,以获取用户的精确位置信息。 百度地图SDK初始化 集成百度地图API时,需要在应用启动时初始化地图SDK。通常在Application类或Activity的onCreate()方法中调用BMapManager.init(),并设置回调监听器以处理初始化结果。 MapView的创建 在布局文件中添加MapView组件,它是地图显示的基础。通过设置其属性(如mapType、zoomLevel等),可以控制地图的显示效果。 定位服务的管理 使用百度地图API的LocationClient类来管理定位服务
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值