线程(线程中常用方法)

1.进程:系统进行资源分配调用的独立单元叫进程.每个进程都有自己独立内存空间和系统资源.(正在运行的程序)

cpu时间片:指的是系统资源和内存空间.

2.线程:进程中的一条执行线路.每个线程要执行一个任务.进程中所有线程共享当前这个进程中系统资源和内存空间.

同一个进程中多个线程之间是互抢资源竟争关系.

3.进程与线程的关系:一个进程中可以一个到多个线程;一个线程只属于一个进程.

4.实现线程:有三种实现方式,前两种公司常用,第三种基本不用.

4.1:继承Thread类,来实现线程

eg:public class MyThead extends Thread{
	/**
	 * 重写父类中线程的任务方法
	 */
	@Override
	public void run() {
		for (int i = 1; i <=10; i++) {
			System.out.println(this.name+":"+i);
		}
	}
}
public static void main(String[] args) {
		//创建子线程对象
		MyThead t1=new MyThead();
		MyThead t2=new MyThead();
				
		//启动线程
		t1.start();
		t2.start();
	}

4.2:实现Runnable接口,实现线程.

eg:public class MyRunable implements Runnable{
	/**
	 * 实现父接口中任务方法
	 */
	@Override
	public void run() {
		for (int i = 1; i <=10; i++) {
			System.out.println(Thread.currentThread().getName()+":"+i);
		}
	}
} 

public static void main(String[] args) {
		//创建任务对象
		MyRunable r1=new MyRunable();
		MyRunable r2=new MyRunable();
		//用任务构建线程对象
		Thread t1=new Thread(r1, "线程A");
		Thread t2=new Thread(r2, "线程B");
		//启动线程
		t1.start();
		t2.start();
	}

4.3:实现Callable接口,实现线程(现在基本不用).

5.继承Thread VS 实现Runnable接口的方式实现多线程

5.1:代码简洁性不同:继承Thread的方式实现线程,代码较简洁;实现Runnable接口的方式实现线程,代码较复杂.

5.2:扩展性不同:继承Thread的方式实现线程,不能再继承其他类,只能实现其他接口,所以扩展性较差;实现Runnable接口的方式实现线程,还可以再继承其他类实现其他接口,所以扩展性好.

5.3:资源共享性:继承Thread的方式实现线程,如果想让多个线程执行同一个任务,只能用静态的,静态比较耗资源,共享性不好;实现Runnable接口的方式实现线程,如果想让多个线程执行同一个任务,只需要让这多个线程共用同一个任务对象就可,共享较好.

6.给线程取名:

6.1:用线程对象调用setName("线程名");

6.2:用构造方法给线程取名.

6.3:用属性方式给线程取名.

6.4:用线程默认名称.

7.线程休眠:使当前正在执行的线程以指定的毫秒数暂停执行或暂停资源抢夺,等待时间到了后再重新参加资源抢夺.

语法:Thread.sleep(毫秒); 或 线程对象.sleep(毫秒);

eg:public static void main(String[] args) throws InterruptedException {
		for (int i = 6; i >=1; i--) {
			System.out.println(Thread.currentThread().getName()+":"+i);
			//每输出一个数字就让当前线程休眠一秒钟
			Thread.sleep(1000);
		}
   }

8.线程优先级:线程优先级由1-10,数字越大优先级越高.优先级越高的线程抢占资源的概率越高,但并不一定就能抢得到;优先级越低的线程抢占资源的概率越低,但并不一定抢不到.

注意:一定要在线程启动之前设置线程优先级.

语法:线程对象.setPriority(int newPriority)

eg:public static void main(String[] args) {
		//创建线程对象
		MyThead t1=new MyThead();
		MyThead t2=new MyThead();

		//设置线程优先级
		t1.setPriority(Thread.MIN_PRIORITY);
		t2.setPriority(Thread.MAX_PRIORITY);
		
		//启动线程
		t1.start();
		t2.start();
}

9.线程合并:将两个及两个以上的线程合并为一个线程,合并过来的线程先执行完,再执行原来线程.

语法:线程对象.join()

9.1:子线程合并到主线中:合并之前,子线程和主线程互抢资源,当前子线程合并过来后就变成一条执行线路,子线程要先执行完再执行主线程后面的内容.

eg:public class MyThead extends Thread{
	/**
	 * 重写父类中线程的任务方法
	 */
	@Override
	public void run() {
		for (int i = 1; i <=100; i++) {
			System.out.println(Thread.currentThread().getName()+":"+i);
		}
	}
}

public static void main(String[] args) throws InterruptedException {
		//创建一个子线程
		MyThead t1=new MyThead();
		//设置线程名称
		t1.setName("子线程");
		
		//启动子线程
		t1.start();
		
		for (int i = 1; i <=100; i++) {
			System.out.println(Thread.currentThread().getName()+":"+i);
			//当主线程运行到10时,子线程合并过来,子线程先执行完再执行主线程
			if (i==10) {
				t1.join();
			}
		}
	}

9.2:子线程B合并到子线程A中:合并之前,两个线程互抢资源,子线程B合并子线程A后,子线程B要先执行完,再执行子线程A.

eg:public class MyThead2 extends Thread{
	//声明一个属性,存线程对象
	public MyThead2 t;
	
	//通过构造方法给线程取名
	public MyThead2(String name) {
		super(name);
	}

	/**
	 * 重写父类中线程的任务方法
	 */
	@Override
	public void run() {
		for (int i = 1; i <=100; i++) {
			System.out.println(Thread.currentThread().getName()+":"+i);
			//如果线程A运行到10,
			if ("线程A".equals(Thread.currentThread().getName())&&i==10) {
				//让线程B合并过来,this指代当前线程A对象
				try {
					this.t.join();
				} catch (InterruptedException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
		}
	}
}

	public static void main(String[] args) {
		//创建线程对象
		MyThead2 t1=new MyThead2("线程A");
		MyThead2 t2=new MyThead2("线程B");
		
		//将线程B对象作为线程A对象的属性传过来
		t1.t=t2;
		
		//启动线程
		t1.start();
		t2.start();
	}

10.线程礼让:暂停一下当前线程正在执行任务或资源的抢占,再接着执行任务或抢占资源.

语法:Thread.yield() 或 线程对象.yield()

eg:public static void main(String[] args) {
		//创建子线程
		MyThead t1=new MyThead();
		
		//启动线程
		t1.start();
		
		for (int i = 1; i <=100; i++) {
			System.out.println(Thread.currentThread().getName()+":"+i);
			//主线程每运行一次就要礼让一下
			Thread.yield();
		}
	}

11.线程中断

11.1:用中断方法改变中断状态,再根据中断状态来中断线程.

eg:public class MyThead1 extends Thread{
	/**
	 * 重写父类中线程的任务方法
	 */
	@Override
	public void run() {
		for (int i = 1; i <=100; i++) {
			//判断子线程中断状态
			if (Thread.currentThread().isInterrupted()==true) {
				break;
			}
			System.out.println(Thread.currentThread().getName()+":"+i);
		}
	}
}

public static void main(String[] args) throws InterruptedException {
		//创建子线程
		MyThead1 t1=new MyThead1();
		//启动线程
		t1.start();
		
		for (int i = 1; i <=100; i++) {
			if (i==10) {
				t1.interrupt();//改变线程中断状态
				Thread.sleep(2000);
			}
			System.out.println(Thread.currentThread().getName()+":"+i);
		}
	}

11.2:在线程类中声明一个变量作标记,标记是否中断线程

eg:public class MyThead2 extends Thread{
	//声明一个变量作标记,标记是否中断线程,默认不中断
	public boolean flag=false;
	
	/**
	 * 重写父类中线程的任务方法
	 */
	@Override
	public void run() {
		for (int i = 1; i <=100; i++) {
			//根据标记判断子线程是否中断
			if (flag) {
				break;
			}
			System.out.println(Thread.currentThread().getName()+":"+i);
		}
	}
}

		public static void main(String[] args) throws InterruptedException {
		//创建子线程
		MyThead2 t1=new MyThead2();
		//启动线程
		t1.start();
		
		for (int i = 1; i <=100; i++) {
			if (i==10) {
				//改变线程中断标记
				t1.flag=true;
				Thread.sleep(2000);
			}
			System.out.println(Thread.currentThread().getName()+":"+i);
		}
	}

12.守护线程(后台线程,精灵线程):守护所有的非守护线程,当所有非守护线程全部死亡,那么守护线程无论有没有执行完都会死亡.

前提:在线程启动之前设置线程是否为守护线程.

语法:线程对象.setDaemon(boolean on)

eg:public static void main(String[] args) {
		//创建一个子线程
		MyThead t1=new MyThead();
		//将子线程设置为守护线程
		t1.setDaemon(true);
		//启动线程
		t1.start();
		
		for (int i = 1; i <=100; i++) {
			System.out.println(Thread.currentThread().getName()+":"+i);
			//子线程把资源抢过去,还得运行一下
		}
	}

13.线程生命周期:

新建状态:刚New出来的线程对象就处于新建状态.

就绪状态:当线程调用start()或当阻塞状态的线程醒来后就处于就绪状态.

运行状态:当就绪状态的线程抢到资源运行run()时就处于运行状态.

阻塞状态:当线程调用sleep()或wait()时就处于阻塞状态.

死亡状态:当线程再也不执行了就处于死亡状态.

1.临界资源问题:在同一个进程中有多个线程执行同一任务,有一个共享资源,当一个线程操作共享资源时,还没来得及修改,另一个线程把cpu时间片抢去了,又来操作共享资源,这时就出现.临界资源问题.

2.解决临界资源问题,要用到线程同步.

3.线程同步:让想一起执行代码绑定成一个代码块,一个线程进去执行这个代码块,其他线程就不能进去,只能在外面等待,等待代码块中线程执行完了,让代码块共享资源让出来,哪个线程抢到cpu时间片就可以进入代码块中执行了,这就是线程同步.

4.线程同步的方式:

4.1:同步代码块:有一个线程进入同步代码块自动上锁,这个线程对象把同步代码块中代码执行完了就会自动解锁.

4.1.1:语法:

synchronized (锁对象) {
	想要一起执行代码块;
 }

4.1.2:同步代码块锁对象可以是任何对象,只要这个锁对象是这多个线程共享,锁对象的值一般不变.

4.1.3:同步代码块中锁范围越小越好.

eg:public class MyRunnable implements Runnable {
	//声明一个成员变量存票数
	public int ticket=1000;
	
	//创建一个锁对象,所有线程共享
	Object ob=new Object();
	
	/**
	 * 实现父类的任务方法
	 */
	@Override
	public void run() {
		while (ticket>0) {//ticket=1
			//1,2,3
			//同步代码块
			synchronized (ob) {//1,2
				if (ticket>0) {
					System.out.println(Thread.currentThread().getName()+"正在销售第"+ticket+"张票");
					ticket--;
				}
			}
		}
	}
}

4.2:同步方法:

synchronized修饰方法 表示同一时间 只能有一个线程执行这个方法

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值