黑马程序员技术交流社区
标题:
线程的问题
[打印本页]
作者:
zhangx
时间:
2013-4-14 09:08
标题:
线程的问题
本帖最后由 zhangx 于 2013-4-14 19:28 编辑
java中有几种方法可以实现一个线程?用什么关键字修饰同步方法?stop()和suspend()方法为什么不推荐使用?
作者:
张先龙
时间:
2013-4-14 09:20
创建的方法有两个:
扩展java.lang.Thread类。
创建Thread 的子类并重写run()方法。run()方法中的代码就是你线程需要执行的代码了。之后创建该类的实例对象。并用该对象调用start()方法,这样,一个线程就启动了,重复这个动作就启动了多个线程。看下面的例子
class ThreadOne extends Thread
{
public void run()
{
for (int i=0;i<40;i++ )
{
System.out.println("ONE线程开始");
}
}
}
class ThreadTwo extends Thread
{
public void run()
{
for(int i=0; i<40;i++)
{
System.out.println("TWO线程开始");
}
}
}
class ThreadDemo
{
public static void main(String[] args)
{
ThreadOne one=new XianOne();
ThreadTwo two=new XianTwo();
one.start();
tow.start();
for(int i=0;i<100;i++)
{
System.out.println("主线程");
}
}
}
运行一下这段代码就会发现“主线程”、“ONE线程开始”、“TWO线程开始”这三个字符串交替出现。
2、创建一个类实现java.lang.Runnable接口。
同样需要覆写run()方法,和上面的例子不同的是,多个线程执行的是同一个run()方法。使用实现接口 Runnable 的对象创建一个线程时,启动该线程将导致在独立执行的线程中调用对象的 run 方法。看下面的例子:
class MyThread implements Runnable
{
public void run()
{
System.out.println("调用了run()方法");
for(int i=0;i<=100;i++)
{
System.out.println(Thread.currentThread().getName());
}
}
}
class MyThreadDemo
{
public static void main(String[] args)
{
MyThread th=new MyThread();
new Thread(th).start();
new Thread(th).start();
new Thread(th).start();
}
}
stop方法具有固有的不安全性。用 Thread.stop 来终止线程将释放它已经锁定的所有监视器。如果以前受这些监视器保护的任何对象都处于一种不一致的状态,则损坏的对象将对其他线程可见,这有可能导致任意的行为
suspend()具有固有的死锁倾向。自然不敢多用。
作者:
段旭东
时间:
2013-4-14 09:21
有两种实现方法,分别是继承Thread类与实现Runnable 接口
用synchronized关键字修饰同步方法
反对使用stop(),是因为它不安全。它会解除由线程获取的所有锁定,而且如果对象处于一种不连贯状态,那么
其他线程能在那种状态下检查和修改它们。结果很难检查出真正的问题所在。suspend()方法容易发生死锁。调用
suspend()的时候,目标线程会停下来,但却仍然持有在这之前获得的锁定。此时,其他任何线程都不能访问锁定
的资源,除非被"挂起"的线程恢复运行。对任何线程来说,如果它们想恢复目标线程,同时又试图使用任何一个
锁定的资源,就会造成死锁。所以不应该使用suspend(),而应在自己的Thread类中置入一个标志,指出线程应该
活动还是挂起。若标志指出线程应该挂起,便用wait()命其进入等待状态。若标志指出线程应当恢复,则用一个
notify()重新启动线程。
作者:
①人←①城市
时间:
2013-4-14 09:31
其他几点说的差不多了,我说下线程同步把
同步(阻塞) :是一种防止对共享资源访问导致的数据不一致的一种模式。
详细请参看操作系统。
在Java中,由于对多线程的支持,对同步的控制主要通过以下几个方法,synchronized,和wait(),notify()和notifyAll()
A关键字synchronized
每个java对象都有一把锁, 当有多个线程同时访问共享资源的时候, 需要Synchronize 来控制安全性, synchronize 分 synchronize 方法 和synchronize块,使用synchronize块时, 一定要显示的获得该对象的锁(如synchronize(object))而方法则不需要。
java的内存模型是对每一个进程有一个主内存, 每个线程有自己的内存, 他们从主内存中取数据, 然后计算, 再存入主内存中。
并发问题如下:如果多个线程同事操作同一数据, A线程从主内存中取的I的值为1, 然后进行加1操作, 这时B线程也取I的值, 进行加2操作, 然后A存入2到主内存中, B也存入, 这样就覆盖了A的值(同数据库中的并发问题一样)。
解决办法是用synchronize, 如用synchronized(I)。被synchronize 修饰的方法(块)把以下三步操作当成一个原子操作:取数据, 操作数据, 存数据。 我们知道原子操作是不可以被打断的, 所以其保证了数据一致性, 这样同一时间只有一个线程再执行, 对性能有一定的影响。这也是synchronize的第二个作用:保证统一时间只有一个线程再运行。 当实现SOCKET连接的时候经常用到.
JAVA中规定对非FLOAT, LONG的原始类型的取和存操作为原子操作。 其实就是对一个字(32位)的取,存位原始操作, 因为FLOAT, LONG为两个字节的长度, 所以其取, 存为非原子操作。 如果想把他们也变为原子操作, 可以用VOLATILE关键字来修饰
使用方法:
作用区域主要有两种:
1.方法
2.代码块
被synchronized声明的方法被称为同步方法,被其修饰的代码块称为同步语句。无论是同步方法还是同步语句,只要声明为同步了,在同一时刻,同一个对象的同步XX是不可以被同时访问的,而不同对象之间的同步方法是互不干扰的。
具体实现(如下代码都在某个类定义中):
同步方法:
Public synchronized void change() {
//
}
同步语句:(因为效率问题,有时考虑使用同步语句块)
Public void change() {
Synchronized(this) {
}
}
这个同步语句是针对当前对象的,有时,我们就是想让一段代码同步,可能与当前对象并没什么关系,可以自定义同步的锁。如下:
private byte[] lock= new byte[0];
Public void change() {
Synchronized(lock) {
}
}
自定义锁注意事项:
1必须是private,防止在类外部引用改变。
2如果可能用到,重写get方法,返回对象的clone,而不是本身。
其他用法:
Synchronized除了可以作用于方法,代码块,还可以作用于静态方法,类,某个实例。但是都存在效率问题,一定要慎用。
Class Foo {
public synchronizedstatic void methodAAA()// 同步的static 函数
{
//….
}
public void methodBBB() {
synchronized(Foo.class)// class literal(类名称字面常量)
} }
这样修饰后代表的是:统一时刻,被修饰部分只有一个对象可以运行,因为它的声明是针对类的。
2.wait()/notify()/notifyAll()
注意:
在Java中,每个对象都有个对象锁标志(Object lock flag)与之想关联,当一个线程A调用对象的一段synchronized代码时,
它首先要获取与这个对象关联的对象锁标志,然后执行相应的代码,执行结束后,把这个对象锁标志返回给对象;因此,在线程A执行
synchronized代码期间,如果另一个线程B也要执行同一对象的一段synchronized代码时(不一定与线程A执行的相同),它将
要等到线程A执行完后,才能继续....
欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/)
黑马程序员IT技术论坛 X3.2