多线程的基本操作方法

多线程的所有操作方法基本上都在Thread类之中定义的,所以研究方法也就是Threa类的翻译,看主要三组方法。

1.线程的命名和取得

在整个多线程的操作之中,名称是最重要的,因为多线程的运行状态是不确定的,那么系统只能够根据名字来判断出是哪一个线程,线程命名的时候不要有重复,更不要修改。
在Thread类提供了如下的几个方法进行名称操作:
构造方法:public Thread(Runnable target,String name)
设置名字:public final void setName(String name)
取得名字 :public final String getName()

问题是线程的运行状态不确定,所以要想取得线程的名字,只能够取得当前正在执行的线程。
那么在这样情况下要想取得当前的线程对象,就必须依靠Thread类的方法:
public static Thread currentThread()

范例:取得当前名字
package thread;
class MyThr implements Runnable{
@Override
public void run() {
System.out.println(Thread.currentThread().getName());
}
}
public class Threade {
public static void main(String[] args) {
// TODO Auto-generated method stub
MyThr mt=new MyThr();
new Thread(mt).start();
new Thread(mt).start();
new Thread(mt,"带名字").start();
}
}
发现此时如果设置了线程名称,那么就返回设置的数据,如果没有设置线程名字会自动的进行命名,以保证每一个线程一定有一个名字。(存在static命名)
范例:观察下面代码
package thread;
class MyThre implements Runnable{
@Override
public void run() {
System.out.println(Thread.currentThread().getName());
}
}
public class Threadea {
public static void main(String[] args) {
// TODO Auto-generated method stub
MyThre mt=new MyThre();
new Thread(mt,"自定义线程").start();
mt.run();
}
}
现在发现通过“mt.run();”执行的时候取得的 线程名称是main,所以可以得出结论:主方法也是一个线程,而新得问题出现了,线程依附于进程,而进程在那里?
每当用户使用java命令解释一个类的时候,对操作系统而言,都会默认启动一个java的进程,而主方法只是这进程之中的一个线程而已。
问题:每一个JVM运行时至少启动几个线程昵?
至少启动两个线程:主线程和GC垃圾回收线程


线程的休眠
线程的休眠指的是让程序暂缓, 休眠方法:public static void sleep(long millis) throwsInteruptedException 
范例:观察休眠
package thread;
class MyThrea implements Runnable{
@Override
public void run() {//线程的主方法
for(int x=0;x<100;x++) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+"x="+x);
}
}
}
public class Threadf {
public static void main(String[] args) {
// TODO Auto-generated method stub
MyThrea mt=new MyThrea();
new Thread(mt,"线程A:").start();
new Thread(mt,"线程B:").start();
new Thread(mt,"线程C:").start();
new Thread(mt,"线程D:").start();
new Thread(mt,"线程E:").start();
}


}
由于线程资源的间隔太短,那么可以简单理解为: 多个线程有可能会同时进入到方法执行。


线程的优先级
从理论上讲线程的优先级越高,越有可能先执行,但这也是只是可能,如果要想进行线程的优先级操作,可以使用如下的两个方法:
设置优先级:public final void setPriority(int newPriority)
取得优先级:public final int getPriority()
对于优先级在Thread类之中定义了三个常量:
最高优先级:public static final int MAX_PRIORITY  ,10;
中等优先级:public static final int NORM_PRIORITY  ,5:
最低优先级:public static final int MIN_PRIORITY   ,1:

范例:观察优先级改变
package thread;
class My implements Runnable{
@Override

public void run() {
for(int x=0;x<20;x++) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+"x="+x);
}
}
}
public class Threadfa {
public static void main(String[] args) {
// TODO Auto-generated method stub
My mt=new My();
Thread t1=new Thread(mt,"线程A:");
Thread t2=new Thread(mt,"线程B:");
Thread t3=new Thread(mt,"线程C:");
t1.setPriority(Thread.MAX_PRIORITY);
t3.setPriority(Thread.MIN_PRIORITY);
t1.start();
t2.start();
t3.start();
}
}
问题;请问主线程的优先级时多少昵?
5,主线程只是个中等优先级
package thread;
class My implements Runnable{
@Override
public void run() {
for(int x=0;x<20;x++) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+"x="+x);
}
}
}
public class Threadfa {
public static void main(String[] args) {
// TODO Auto-generated method stub
System.out.println(Thread.currentThread().getPriority());
}
}


线程的同步与死锁
1.线程的同步
当多个线程访问同一资源的时候一定需要考虑到同步问题,那么下面通过一个卖票程序,观察不同步的问题
package thread;
class Mya implements Runnable{
private int ticket=8;//一共8张票
@Override
public void run() { //线程的主方法
for(int x=0;x<20;x++) {
if(this.ticket>0) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+",ticket="+this.ticket--);
}
}
}
}
public class Threadg {
public static void main(String[] args) {
// TODO Auto-generated method stub
Mya mt=new Mya();
new Thread(mt,"票贩子A").start();
new Thread(mt,"票贩子B").start();
new Thread(mt,"票贩子C").start();
new Thread(mt,"票贩子D").start();
new Thread(mt,"票贩子E").start();
new Thread(mt,"票贩子F").start();
}
}
那么在这个时候就发生了不同步的情况,而发生的原因也很简单,对于整个买票过程实际上时两步完成的
第一步:使用if语句是否有票:
第二步:进行票数的修改
此时可能出现这种情况,如果说现在只有最后一张票了,可以满足if条件判断,所以线程可以通过if语句拦截,可是在修改票之前出现一个延迟操作,那么有可能在这个延迟的过程之中,又出现其它线程进入到方法之中,由于此时没有修改票数,那么这个线程也可以满足if条件判断,后面的线程依次类推,所以当休眠时间一过,进行票数修改的时候,都将在已有的票数上修改,自然会出现负数。
问题的解决关键是需要一把锁。
如果要想上好这把“锁”,则可以采用两种方式完成:同步代码块,同步方法
范例:使用同步代码块
同步代码块式使用synchronized关键字定义的代码块,但是在进行同步的时候一定要设置好一个同步对象,所以同步对象一般使用当前对象this表示
package thread;
class Myb implements Runnable{
private int ticket=8;//一共8张票
@Override
public void run() { //线程的主方法
for(int x=0;x<20;x++) {
synchronized(this) {
if(this.ticket>0) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+",ticket="+this.ticket--);
}
}
  } 
}
}
public class Threadga {
public static void main(String[] args) {
// TODO Auto-generated method stub
Myb mt=new Myb();
new Thread(mt,"票贩子A").start();
new Thread(mt,"票贩子B").start();
new Thread(mt,"票贩子C").start();
new Thread(mt,"票贩子D").start();
new Thread(mt,"票贩子E").start();
new Thread(mt,"票贩子F").start();
}


}
此时的程序执行速度变得明显缓慢了,因为需要一个个排队进行。虽然性能变慢了,但是数据的安全性提高了,也就是说异步处理(不加synchronized)和同步处理(使用synchronized)的区别也在于此。
范例:同步方法实现
如果在一个方法的声明上使用了synchronized关键字,则表示此方法式一个同步方法。
package thread;
class Myc implements Runnable{
private int ticket=8;//一共8张票
@Override
public void run() {
for(int x=0;x<20;x++) {
this.sale();
}
}
public synchronized void sale() {
if(this.ticket>0) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+",ticket="+this.ticket--);
  }
}
}
public class Threadgb {
public static void main(String[] args) {
// TODO Auto-generated method stub
Myc mt=new Myc();
new Thread(mt,"票贩子A").start();
new Thread(mt,"票贩子B").start();
new Thread(mt,"票贩子C").start();
new Thread(mt,"票贩子D").start();
new Thread(mt,"票贩子E").start();
new Thread(mt,"票贩子F").start();
}
}
同步的核心意义:一个线程要等待另一个线程执行完毕。


死锁(看懂结论)
//下面代码只是演示死锁出现的状况,当代码本身没有意义
所谓的死锁就是指的互相等待的情况
结论:多个线访问同一资源的时候一定考虑到线程的同步,但是同步会影响程序的性能,同时会提升数据的安全性,过多的同步会有可能出现死锁。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值