Java多线程编程

进程:

正在运行的程序。代表着一个应用程序的内存空间。

在该空间中需要对该应用程序的代码进行执行控制。

每一个控制代码执行流程的单元称为线程


线程:

是进程中一个独立的控制单元,也称为执行路径,执行情景,一个进程中至少有一个线程

Jvw虚拟机在执行一个java程序时,至少启动了了两个线程;

一个是主线程,该线程执行的是main函数中的代码

另一个是垃圾回收线程,执行垃圾回收的代码;

多线程技术可以有多个执行路径,让多部分代码实现同时执行(单核的CPU,执行过程中其实是在做着快速的切换)


创建线程的方式:

一:继承Thread

1  定义类继承Thread类,作为线程类的子类

2  定义线程要运行的代码,并将代码存储到Thread类的run方法中

(主线程要运行的代码定义在main函数中,自定义要运行的代码定义在run方法中)


3  调用线程类的start方法开启线程,并执行线程的run方法

运行时会发现结果每一次都有可能不一样。那是因为cpu在做着快速切换完成的,执行过程中,是按照cpu的特点执行,没有什么规则,所以,多线程运行时,有一个特性:随机性。线程有自己默认的名称Thread-编号,从0开始编号可以通过Thread类中的方法进行获取:

static Thread currentThread():返回当前线程对象。

String getName():获取线程对象的名称。

class Demo extends Thread{
	private String name;
	Demo(String name){
		this.name = name;
	}
	public void run(){
		for(int x=0; x<30; x++){
 	    		for(long y=-9999990; y<100000000; y++){}
			System.out.println(name+"。。。"+x+"...."+Thread.currentThread().getName());
		}
	}
}


class ThreadDemo {
	public static void main(String[] args) {
		Demo d1 = new Demo("one---");
		Demo d2 = new Demo("two");
		d1.start();
    		d2.start();
		for(int x=0; x<30; x++){
			System.out.println("hello main....."+x+"...."+Thread.currentThread().getName());
		}
	}
}

二 、实现Runnable接口

定义类实现Runnable接口

覆盖Runnable接口中的run方法,将多线程要运行的代码存放该run方法中

通过Thread类创建线程对象

将实现了Runnable接口的子类对象作为实际参数传递给Thread类的构造函数。


为什么要将Runnable接口的子类对象作为参数传递呢?

是为了告诉多线程要运行的代码所属的对象。调用Thread类的start方法让线程启动并运行。


class Demo implements Runnable{
	private String name;
	Demo(String name){
		this.name = name;
	}
	public void run(){
		for(int x=0; x<30; x++){
       			for(long y=-9999990; y<100000000; y++){}
			System.out.println(name+"。。。"+x+"...."+Thread.currentThread().getName());
		}
	}
}


class ThreadDemo {
	public static void main(String[] args) {
		Demo d1 = new Demo("one---");
		Demo d2 = new Demo("two");
		Thread t1= new Thread(d1);
		Thread t2= new Thread(d2);
		t1.start();
   	  	t2.start();
		for(int x=0; x<30; x++){
			System.out.println("hello main....."+x+"...."+Thread.currentThread().getName());
		}
	}
}

继承Thread类和实现Runnable接口的区别:

实现Runnable接口可以避免单继承的局限性

所以,在创建线程是建议使用第二种方式

其实该接口在设计时,就是将线程要运行代码的位置进行抽取


线程安全问题产生的原因:

当多个线程对操作共性数据的多句代码分开执行导致的

要素: 共性数据、 多句操作共性数据的代码


解决该问题的原理:

保证多条操作共性数据的代码在同一时间段只有一个线程在执行,在执行期间,不允许其他线程参与

解决方式:Java提供了解决方案,就是同步机制。

代码体现:同步代码块。

Synchronized(任意对象){

//需要被同步封装的语句

}

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


同步前提:

         1  必须要有两个或者两个以上的线程。

         2   多个线程必须使用同一个锁

如果加上同步问题没被解决就是前提出错


 同步弊端:

 降低运行效率,对资源是一种消耗。       

同步代码块是一个封装体,函数也是一个封装体,如果让函数具备了同步性,那么就没有必要定义同步代码块了。这个函数就称为同步函数。

同步函数锁使用的锁是this

同步函数和同步代码块的区别:

同步函数使用的锁是固定的this

同步代码块可以指定任意的对象作为锁

一般开发常用同步代码块

静态同步函数所使用的锁是:所属类的字节码文件对象,写法是类名.class

死锁:在同步嵌套的时候,容易出现死锁

            要尽量避免死锁。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值