- 浏览: 297923 次
- 性别:
- 来自: 北京
文章分类
最新评论
-
刘燕宝宝鱼:
fengqiyuanluo 写道q77102902 写道DAO ...
spring事务管理几种方式(转) -
zweichxu:
q77102902 写道DAO层注解加的有问题,不要误导新人, ...
spring事务管理几种方式(转) -
jsolo:
q77102902 写道DAO层注解加的有问题,不要误导新人, ...
spring事务管理几种方式(转) -
fengqiyuanluo:
q77102902 写道DAO层注解加的有问题,不要误导新人, ...
spring事务管理几种方式(转) -
q77102902:
DAO层注解加的有问题,不要误导新人,DAO层注解应该是@Re ...
spring事务管理几种方式(转)
说明:此文档,只是对之前多线程,socket,文件读写三个文档中的基础,关键部分作一次整合。因为socket中会用到多线程,及文件读写,方便整体阅读。
------------------------------------多线程----------------------------------
多线程:
0.
多线程的概念:
多线程是这样一种机制,它允许在程序中并发执行多个线程,且每个线程彼此间互相独立。
并发的理解:
多个线程的执行是并发的,也就是在逻辑上“同时”,而不管是否是物理上的“同时”。
1.
实现线程的方式有两种:
1、继承java.lang.Thread,并重写它的run()方法,将线程的执行主体放入其中。
2、实现java.lang.Runnable接口,实现它的run()方法,并将线程的执行主体放入其中。
==>多线程的执行逻辑:
当主线程被挂起时, 其它就绪的线程会根据选择最高优先级的来执行;
当主线程的挂起时间 > 子线程的执行时间时,子线程执行完后回到主线程,等待主线程醒来.
当主线程的挂起时间 < 子线程的执行时间时,主线程挂起时间到的,自动醒来,回到主线程,此时可以判断子线程是否存在,若有,可stop之.
上面两种实现线程的方式在启动时会有所不同。
# ThreadTest tt = new ThreadTest();
# // 启动线程
# tt.start();
# // 创建一个线程实例
# Thread t = new Thread(new RunnableTest());
# // 启动线程
# t.start();
2.
线程状态的具体信息如下:
1. NEW(新建状态、初始化状态):线程对象已经被创建,但是还没有被启动时的状态。这段时间就是在我们调用new命令之后,调用start()方法之前。
2. RUNNABLE(可运行状态、就绪状态):在我们调用了线程的start()方法之后线程所处的状态。
3. BLOCKED(阻塞状态、被中断运行):
4.TERMINATED(死亡状态、终止状态):线程完成执行后的状态。或run()在运行过程中抛出了一个异常,而这个异常没有被程序捕获,导致这个线程异常终止进入TERMINATED状态。
3.
你可以调用 Thread 类的方法 getPriority() 和 setPriority()来存取线程的优先级,线程的优先级界于1(MIN_PRIORITY)和10(MAX_PRIORITY)之间,缺省是5(NORM_PRIORITY)。
4.
同步synchronized
重点理解:
synchronized 方法,用来控制对类成员变量的访问:每个类实例对应一把锁,每个 synchronized 方法都必须获得调用该方法的类实例的锁方能执行,否则所属线程阻塞;方法一旦执行,就独占该锁,直到从该方法返回时才将锁释放;此后被阻塞的线程方能获得该锁,重新进入可执行状态。这种机制确保了同一时刻对于每一个类实例,其所有声明为 synchronized 的成员函数中至多只有一个处于可执行状态.
也就是说:
线程在执行同步方法时是具有排它性的。当任意一个线程进入到一个对象的任意一个同步方法时,这个对象的所有同步方法都被锁定了,在此期间,其他任何线程都不能访问这个对象的任意一个同步方法,直到这个线程执行完它所调用的同步方法并从中退出,从而导致它释放了该对象的同步锁之后。在一个对象被某个线程锁定之后,其他线程是可以访问这个对象的所有非同步方法的。
在 Java 中,不光是类实例,每一个类也对应一把锁,这样我们也可将类的静态成员函数声明为 synchronized ,以控制其对类的静态成员变量的访问。
同步块也一样:
一、当两个并发线程访问同一个对象object中的这个synchronized(this)同步代码块时,一个时间内只能有一个线程得到执行。另一个线程必须等待当前线程执行完这个代码块以后才能执行该代码块。
二、然而,当一个线程访问object的一个synchronized(this)同步代码块时,另一个线程仍然可以访问该object中的非synchronized(this)同步代码块。
三、尤其关键的是,当一个线程访问object的一个synchronized(this)同步代码块时,其他线程对object中所有其它synchronized(this)同步代码块的访问将被阻塞。
基本格式:
同步方法:
同步方法:
添加了同步后,结果:
A 's num is 100
A 's num is 99
A 's num is 98
A 's num is 97
A 's num is 96
B 's num is 95
B 's num is 94
B 's num is 93
B 's num is 92
B 's num is 91
若不添加同步:
A 's num is 100
A 's num is 98
A 's num is 97
A 's num is 96
A 's num is 95
B 's num is 99 --此处
B 's num is 94
B 's num is 93
B 's num is 92
B 's num is 91
说明:
则线程A正在处理的中间数据若结果数据(99),将线程B中调用了;A又调用了线程B的中间数据,继续计算.
注意:
在定义接口方法时不能使用synchronized关键字。
构造方法不能使用synchronized关键字,但可以使用下节要讨论的synchronized块来进行同步。
3.
Lock是一个接口,它位于Java 5.0新增的java.utils.concurrent包的子包locks中。实现Lock接口的类具有与synchronized关键字同样的功能,但是它更加强大一些。java.utils.concurrent.locks.ReentrantLock是较常用的实现了Lock接口的类。上面的实例可以变为:
注意:
引入了锁,但是锁的引入常常会造成一个很大的问题——死锁 。
死锁就是一个进程中的每个线程都在等待这个进程中的其他线程释放所占用的资源,从而导致所有线程都无法继续执行的情况。
4.
线程的阻塞
阻塞指的是暂停一个线程的执行以等待某个条件发生(如某资源就绪),Java 提供了大量方法来支持阻塞,下面让我们逐一分析。
1. sleep() 方法:sleep() 允许指定以毫秒为单位的一段时间作为参数,它使得线程在指定的时间内进入阻塞状态,不能得到CPU 时间,指定的时间一过,线程重新进入可执行状态。
2. suspend() 和 resume() 方法:两个方法配套使用,suspend()使得线程进入阻塞状态,并且不会自动恢复,必须其对应的resume() 被调用,才能使得线程重新进入可执行状态。
3. yield() 方法:yield() 使得线程放弃当前分得的 CPU 时间,但是不使线程阻塞,即线程仍处于可执行状态,随时可能再次分得 CPU 时间。
4. wait() 和 notify() 方法:两个方法配套使用,wait() 使得线程进入阻塞状态,它有两种形式,一种允许指定以毫秒为单位的一段时间作为参数,另一种没有参数,前者当对应的 notify() 被调用或者超出指定时间时线程重新进入可执行状态,后者则必须对应的 notify () 被调用。
区别:
初看起来 wait() 和 notify()与 suspend() 和 resume() 方法对没有什么分别,但是事实上它们是截然不同的。区别的核心在于,前面叙述的所有方法,阻塞时都不会释放占用的锁(如果占用了的话),而 wait() 和 notify()这一对方法则相反, wait() 方法导致线程阻塞,并且该对象上的锁被释放。
在上面的实例中修改:
若用wait(),则直接输出A,B信息.
JAVA多线程编程。用JAVA写一个多线程程序,如写四个线程,二个加1,二个对一个变量减一,输出。(须考虑同步)
线程池
线程池就像数据库连接池一样,是一个对象池。所有的对象池都有一个共同的目的,那就是为了提高对象的使用率,从而达到提高程序效率的目的.
多线程---守护线程
在Java中有两类线程:User Thread(用户线程)、Daemon Thread(守护线程)
Daemon的作用是为其他线程的运行提供便利服务,比如垃圾回收线程就是一个很称职的守护者。
6.
终止线程三种方式:
当run方法完成后线程终止;
使用stop方法强行终止线程(这个方法不推荐使用,因为stop和suspend、resume一样,也可能发生不可预料的结果);
使用interrupt方法中断线程.
------------------------------------文件读写----------------------------------
I/O操作
对于输入/输出问题,Java将之抽象化为流(Stream)对象来解决。
对输入/输出流,及文件的处理,注意要在最后关闭流或文件,且在处理前后添加try..catch.
Reader、Writer与其子类可以用于进行所谓纯文本文件的字符读/写.
InputStreamReader和OutputStreamWriter (它们分别为Reader和Writer的子类.)
InputStreamReader inputStreamReader = new InputStreamReader(fileInputStream);
OutputStreamWriter outputStreamWriter = new OutputStreamWriter(fileOutputStream);
int ch = 0;
// 以字符方式显示文件内容
while ((ch = inputStreamReader.read()) != -1) {
outputStreamWriter.write(ch);
}
inputStreamReader.close();
outputStreamWriter.close();
FileReader和FileWriter(它们分别继承自InputStreamReader与 OutputStreamWriter)
操作更加简单,不用先建input/outputstream,直接将路径放上去就行.
FileReader fileReader = new FileReader("D:\\jason.txt");
FileWriter fileWriter = new FileWriter("D:\\change.txt");
BufferedReader和BufferedWriter(常用于整行读写,单字读写用上面的两类)
读写效率比较高,但须先创建InputStreamReader/OutputStreamWriter或FileReader/FileWriter作为其参数
try {
BufferedReader reader=new BufferedReader(new FileReader("D:\\jason.log"));
BufferedWriter writer=new BufferedWriter(new FileWriter("D:\\change.txt"));
String show=reader.readLine(); //读取第一行信息
while(!show.equals("bye"))
{
System.out.println(show);
writer.write(show+"\n"); //其中\n用于换行
show=reader.readLine(); //进行循环读取
}
writer.flush();
reader.close();
writer.close();
} catch (Exception ee) {
ee.printStackTrace();
}
注意:只有BufferedReader或BufferedInputStream,没有BufferedInputStreamReader.
说明:
BufferedReader的readline()方法,实际就是以下的样式的定制:
byte[] a=new byte[2]; --->自己定制缓存的大小,而readline(),则是原先定制好的.
.....
if((ch=A.read(a))!=-1)
{B.wirte(a)}
------------------------------------socket----------------------------------
socket,
对输入/输出流,及文件的处理,注意要在最后关闭流或文件,且在处理前后添加try..catch
我们可以做一个简单的 Socket 例程了 .
服务端 :
注意:只有BufferedReader或BufferedInputStream,没有BufferedInputStreamReader.
这个程序的主要目的在于服务器不断接收客户机所写入的信息直到客户机发送 "End" 字符串就退出程序 . 并且服务器也会做出 "Receive" 为回应 . 告知客户机已接收到消息 .
客户机代码 :
这个程序只是简单的两台计算机之间的通讯 . 如果是多个客户同时访问一个服务器呢 ? 你可以试着再运行一个客户端 , 结果是会抛出异常的 . 那么多个客户端如何实现呢 ?
如何实现多线程并发socket通讯:
服务端socket,负责监听socket端口,设置一个无限循环,在其中实现:将监听到的socket实例赋给线程且启动线程,由线程来完成业务逻辑.具体如下:
import java.net.*;
import java.io.*;
public class MultiUser extends Thread{
private Socket client;
public MultiUser(Socket c){
this.client=c;
}
public void run(){
try{
BufferedReader in=new BufferedReader(new InputStreamReader(client.getInputStream()));
PrintWriter out=new PrintWriter(client.getOutputStream());
//Mutil User but can't parallel
while(true){
String str=in.readLine();
System.out.println(str);
out.println("has receive....");
out.flush();
if(str.equals("end"))
break;
}
client.close();
}catch(IOException ex){
}finally{
}
}
myserver.java修改如下:
public static void main(String[] args)throws IOException{
ServerSocket server=new ServerSocket(5678);
while(true){
//transfer location change Single User or Multi User
MultiUser mu=new MultiUser(server.accept());
mu.start();
}
}
}
2.
用socket传输文件,实际就是打开文件,将内容读取发送到对方,对方获取保存到文件中。
用socket可以传输对象--ObjectInputStream/ObjectOutputStream
1. 对于普通的传输字符串,用 BufferedInputStream /BufferedOutputStream 及 os.println(), is.readline() 即可。
2. 对于文件的传输,用 FileInputStream /FileOutputStream 及 DataInputStream /DataOutputStream 及 os.write(), is.read() 即可。
3. 对于对象的传输,用 ObjectInputStream /ObjectOutputStream 及 os.writeObject(), is.readObject() 即可 .
------------------------------------多线程----------------------------------
多线程:
0.
多线程的概念:
多线程是这样一种机制,它允许在程序中并发执行多个线程,且每个线程彼此间互相独立。
并发的理解:
多个线程的执行是并发的,也就是在逻辑上“同时”,而不管是否是物理上的“同时”。
1.
实现线程的方式有两种:
1、继承java.lang.Thread,并重写它的run()方法,将线程的执行主体放入其中。
2、实现java.lang.Runnable接口,实现它的run()方法,并将线程的执行主体放入其中。
==>多线程的执行逻辑:
当主线程被挂起时, 其它就绪的线程会根据选择最高优先级的来执行;
当主线程的挂起时间 > 子线程的执行时间时,子线程执行完后回到主线程,等待主线程醒来.
当主线程的挂起时间 < 子线程的执行时间时,主线程挂起时间到的,自动醒来,回到主线程,此时可以判断子线程是否存在,若有,可stop之.
上面两种实现线程的方式在启动时会有所不同。
# ThreadTest tt = new ThreadTest();
# // 启动线程
# tt.start();
# // 创建一个线程实例
# Thread t = new Thread(new RunnableTest());
# // 启动线程
# t.start();
2.
线程状态的具体信息如下:
1. NEW(新建状态、初始化状态):线程对象已经被创建,但是还没有被启动时的状态。这段时间就是在我们调用new命令之后,调用start()方法之前。
2. RUNNABLE(可运行状态、就绪状态):在我们调用了线程的start()方法之后线程所处的状态。
3. BLOCKED(阻塞状态、被中断运行):
4.TERMINATED(死亡状态、终止状态):线程完成执行后的状态。或run()在运行过程中抛出了一个异常,而这个异常没有被程序捕获,导致这个线程异常终止进入TERMINATED状态。
3.
你可以调用 Thread 类的方法 getPriority() 和 setPriority()来存取线程的优先级,线程的优先级界于1(MIN_PRIORITY)和10(MAX_PRIORITY)之间,缺省是5(NORM_PRIORITY)。
4.
同步synchronized
重点理解:
synchronized 方法,用来控制对类成员变量的访问:每个类实例对应一把锁,每个 synchronized 方法都必须获得调用该方法的类实例的锁方能执行,否则所属线程阻塞;方法一旦执行,就独占该锁,直到从该方法返回时才将锁释放;此后被阻塞的线程方能获得该锁,重新进入可执行状态。这种机制确保了同一时刻对于每一个类实例,其所有声明为 synchronized 的成员函数中至多只有一个处于可执行状态.
也就是说:
线程在执行同步方法时是具有排它性的。当任意一个线程进入到一个对象的任意一个同步方法时,这个对象的所有同步方法都被锁定了,在此期间,其他任何线程都不能访问这个对象的任意一个同步方法,直到这个线程执行完它所调用的同步方法并从中退出,从而导致它释放了该对象的同步锁之后。在一个对象被某个线程锁定之后,其他线程是可以访问这个对象的所有非同步方法的。
在 Java 中,不光是类实例,每一个类也对应一把锁,这样我们也可将类的静态成员函数声明为 synchronized ,以控制其对类的静态成员变量的访问。
同步块也一样:
一、当两个并发线程访问同一个对象object中的这个synchronized(this)同步代码块时,一个时间内只能有一个线程得到执行。另一个线程必须等待当前线程执行完这个代码块以后才能执行该代码块。
二、然而,当一个线程访问object的一个synchronized(this)同步代码块时,另一个线程仍然可以访问该object中的非synchronized(this)同步代码块。
三、尤其关键的是,当一个线程访问object的一个synchronized(this)同步代码块时,其他线程对object中所有其它synchronized(this)同步代码块的访问将被阻塞。
基本格式:
同步方法:
public void methodAAA() { synchronized (this) // (1) { //….. } }同步块:
public void methodAAA() { synchronized (this) // (1) { //….. } }实例如下:
同步方法:
public class Thread1 implements Runnable { int num=100; public synchronized void run() { for (int i = 0; i < 5; i++) { System.out.println(Thread.currentThread().getName()+ " 's num is " + num--); } } public static void main(String[] args) { Thread1 t1 = new Thread1(); Thread ta = new Thread(t1, "A"); Thread tb = new Thread(t1, "B"); ta.start(); tb.start(); } }同步块:
public class Thread1 implements Runnable { int num = 100; public void run() { synchronized (this) { for (int i = 0; i < 5; i++) { System.out.println(Thread.currentThread().getName() + " 's num is " + num--); } } } public static void main(String[] args) { Thread1 t1 = new Thread1(); Thread ta = new Thread(t1, "A"); Thread tb = new Thread(t1, "B"); ta.start(); tb.start(); } }
添加了同步后,结果:
A 's num is 100
A 's num is 99
A 's num is 98
A 's num is 97
A 's num is 96
B 's num is 95
B 's num is 94
B 's num is 93
B 's num is 92
B 's num is 91
若不添加同步:
A 's num is 100
A 's num is 98
A 's num is 97
A 's num is 96
A 's num is 95
B 's num is 99 --此处
B 's num is 94
B 's num is 93
B 's num is 92
B 's num is 91
说明:
则线程A正在处理的中间数据若结果数据(99),将线程B中调用了;A又调用了线程B的中间数据,继续计算.
注意:
在定义接口方法时不能使用synchronized关键字。
构造方法不能使用synchronized关键字,但可以使用下节要讨论的synchronized块来进行同步。
3.
Lock是一个接口,它位于Java 5.0新增的java.utils.concurrent包的子包locks中。实现Lock接口的类具有与synchronized关键字同样的功能,但是它更加强大一些。java.utils.concurrent.locks.ReentrantLock是较常用的实现了Lock接口的类。上面的实例可以变为:
public class Thread1 implements Runnable { int num = 100; private Lock lock = new ReentrantLock(); public void run() { try { lock.lock(); for (int i = 0; i < 5; i++) { System.out.println(Thread.currentThread().getName() + " 's num is " + num--); } } catch (Exception e) { e.printStackTrace(); } finally { lock.unlock(); } } public static void main(String[] args) { Thread1 t1 = new Thread1(); Thread ta = new Thread(t1, "A"); Thread tb = new Thread(t1, "B"); ta.start(); tb.start(); } }lock ()方法用于锁定对象,unlock()方法用于释放对对象的锁定,他们都是在Lock接口中定义的方法。位于这两个方法之间的代码在被执行时,效果等同于被放在synchronized同步块中。一般用法是将需要在lock()和unlock()方法之间执行的代码放在try{}块中,并且在 finally{}块中调用unlock()方法,这样就可以保证即使在执行代码抛出异常的情况下,对象的锁也总是会被释放,否则的话就会为死锁的产生增加可能。
注意:
引入了锁,但是锁的引入常常会造成一个很大的问题——死锁 。
死锁就是一个进程中的每个线程都在等待这个进程中的其他线程释放所占用的资源,从而导致所有线程都无法继续执行的情况。
4.
线程的阻塞
阻塞指的是暂停一个线程的执行以等待某个条件发生(如某资源就绪),Java 提供了大量方法来支持阻塞,下面让我们逐一分析。
1. sleep() 方法:sleep() 允许指定以毫秒为单位的一段时间作为参数,它使得线程在指定的时间内进入阻塞状态,不能得到CPU 时间,指定的时间一过,线程重新进入可执行状态。
2. suspend() 和 resume() 方法:两个方法配套使用,suspend()使得线程进入阻塞状态,并且不会自动恢复,必须其对应的resume() 被调用,才能使得线程重新进入可执行状态。
3. yield() 方法:yield() 使得线程放弃当前分得的 CPU 时间,但是不使线程阻塞,即线程仍处于可执行状态,随时可能再次分得 CPU 时间。
4. wait() 和 notify() 方法:两个方法配套使用,wait() 使得线程进入阻塞状态,它有两种形式,一种允许指定以毫秒为单位的一段时间作为参数,另一种没有参数,前者当对应的 notify() 被调用或者超出指定时间时线程重新进入可执行状态,后者则必须对应的 notify () 被调用。
区别:
初看起来 wait() 和 notify()与 suspend() 和 resume() 方法对没有什么分别,但是事实上它们是截然不同的。区别的核心在于,前面叙述的所有方法,阻塞时都不会释放占用的锁(如果占用了的话),而 wait() 和 notify()这一对方法则相反, wait() 方法导致线程阻塞,并且该对象上的锁被释放。
在上面的实例中修改:
public static void main(String[] args) { Thread1 t1 = new Thread1(); Thread ta = new Thread(t1, "A"); Thread tb = new Thread(t1, "B"); ta.start(); try { ta.sleep(10000); } catch (Exception e) {} tb.start(); }在输出A的5条记录后,须等10秒,才输出B的.
若用wait(),则直接输出A,B信息.
JAVA多线程编程。用JAVA写一个多线程程序,如写四个线程,二个加1,二个对一个变量减一,输出。(须考虑同步)
//将要加减的变量设置为static;将加减操作及相应的变量定义在另一类中.在线程中进行调用即可. //只要是多线程,就要考虑其同步.即要用synchrnized class t { private static int x=10; public synchronized void add() { x++; System.out.println("x="+x); } public synchronized void jian() { x--; System.out.println("x="+x); } } class t1 extends Thread { public void run() { t t1=new t(); t1.add(); } } class t2 extends Thread { public void run() { t t1=new t(); t1.jian(); } } public class ThreadTest { public static void main(String [] args) { t1 t11=new t1(); t1 t12=new t1(); t2 t21=new t2(); t2 t22=new t2(); t11.start(); t12.start(); t21.start(); t22.start(); } }5.
线程池
线程池就像数据库连接池一样,是一个对象池。所有的对象池都有一个共同的目的,那就是为了提高对象的使用率,从而达到提高程序效率的目的.
多线程---守护线程
在Java中有两类线程:User Thread(用户线程)、Daemon Thread(守护线程)
Daemon的作用是为其他线程的运行提供便利服务,比如垃圾回收线程就是一个很称职的守护者。
6.
终止线程三种方式:
当run方法完成后线程终止;
使用stop方法强行终止线程(这个方法不推荐使用,因为stop和suspend、resume一样,也可能发生不可预料的结果);
使用interrupt方法中断线程.
------------------------------------文件读写----------------------------------
I/O操作
对于输入/输出问题,Java将之抽象化为流(Stream)对象来解决。
对输入/输出流,及文件的处理,注意要在最后关闭流或文件,且在处理前后添加try..catch.
Reader、Writer与其子类可以用于进行所谓纯文本文件的字符读/写.
InputStreamReader和OutputStreamWriter (它们分别为Reader和Writer的子类.)
InputStreamReader inputStreamReader = new InputStreamReader(fileInputStream);
OutputStreamWriter outputStreamWriter = new OutputStreamWriter(fileOutputStream);
int ch = 0;
// 以字符方式显示文件内容
while ((ch = inputStreamReader.read()) != -1) {
outputStreamWriter.write(ch);
}
inputStreamReader.close();
outputStreamWriter.close();
FileReader和FileWriter(它们分别继承自InputStreamReader与 OutputStreamWriter)
操作更加简单,不用先建input/outputstream,直接将路径放上去就行.
FileReader fileReader = new FileReader("D:\\jason.txt");
FileWriter fileWriter = new FileWriter("D:\\change.txt");
BufferedReader和BufferedWriter(常用于整行读写,单字读写用上面的两类)
读写效率比较高,但须先创建InputStreamReader/OutputStreamWriter或FileReader/FileWriter作为其参数
try {
BufferedReader reader=new BufferedReader(new FileReader("D:\\jason.log"));
BufferedWriter writer=new BufferedWriter(new FileWriter("D:\\change.txt"));
String show=reader.readLine(); //读取第一行信息
while(!show.equals("bye"))
{
System.out.println(show);
writer.write(show+"\n"); //其中\n用于换行
show=reader.readLine(); //进行循环读取
}
writer.flush();
reader.close();
writer.close();
} catch (Exception ee) {
ee.printStackTrace();
}
注意:只有BufferedReader或BufferedInputStream,没有BufferedInputStreamReader.
说明:
BufferedReader的readline()方法,实际就是以下的样式的定制:
byte[] a=new byte[2]; --->自己定制缓存的大小,而readline(),则是原先定制好的.
.....
if((ch=A.read(a))!=-1)
{B.wirte(a)}
------------------------------------socket----------------------------------
socket,
对输入/输出流,及文件的处理,注意要在最后关闭流或文件,且在处理前后添加try..catch
我们可以做一个简单的 Socket 例程了 .
服务端 :
import java.io.*; import java.net.*; public class MyServer { public static void main(String[] args) throws IOException{ ServerSocket server=new ServerSocket(5678); Socket client=server.accept(); BufferedReader in=new BufferedReader(new InputStreamReader(client.getInputStream())); PrintWriter out=new PrintWriter(client.getOutputStream()); while(true){ String str=in.readLine(); System.out.println(str); out.println("has receive...."); out.flush(); if(str.equals("end")) break; } client.close(); } }
注意:只有BufferedReader或BufferedInputStream,没有BufferedInputStreamReader.
这个程序的主要目的在于服务器不断接收客户机所写入的信息直到客户机发送 "End" 字符串就退出程序 . 并且服务器也会做出 "Receive" 为回应 . 告知客户机已接收到消息 .
客户机代码 :
import java.net.*; import java.io.*; public class Client{ static Socket server; public static void main(String[] args)throws Exception{ server=new Socket(InetAddress.getLocalHost(),5678); BufferedReader in=new BufferedReader(new InputStreamReader(server.getInputStream())); PrintWriter out=new PrintWriter(server.getOutputStream()); BufferedReader wt=new BufferedReader(new InputStreamReader(System.in)); while(true){ String str=wt.readLine(); out.println(str); out.flush(); if(str.equals("end")){ break; } System.out.println(in.readLine()); } server.close(); } }
这个程序只是简单的两台计算机之间的通讯 . 如果是多个客户同时访问一个服务器呢 ? 你可以试着再运行一个客户端 , 结果是会抛出异常的 . 那么多个客户端如何实现呢 ?
如何实现多线程并发socket通讯:
服务端socket,负责监听socket端口,设置一个无限循环,在其中实现:将监听到的socket实例赋给线程且启动线程,由线程来完成业务逻辑.具体如下:
import java.net.*;
import java.io.*;
public class MultiUser extends Thread{
private Socket client;
public MultiUser(Socket c){
this.client=c;
}
public void run(){
try{
BufferedReader in=new BufferedReader(new InputStreamReader(client.getInputStream()));
PrintWriter out=new PrintWriter(client.getOutputStream());
//Mutil User but can't parallel
while(true){
String str=in.readLine();
System.out.println(str);
out.println("has receive....");
out.flush();
if(str.equals("end"))
break;
}
client.close();
}catch(IOException ex){
}finally{
}
}
myserver.java修改如下:
public static void main(String[] args)throws IOException{
ServerSocket server=new ServerSocket(5678);
while(true){
//transfer location change Single User or Multi User
MultiUser mu=new MultiUser(server.accept());
mu.start();
}
}
}
2.
用socket传输文件,实际就是打开文件,将内容读取发送到对方,对方获取保存到文件中。
用socket可以传输对象--ObjectInputStream/ObjectOutputStream
1. 对于普通的传输字符串,用 BufferedInputStream /BufferedOutputStream 及 os.println(), is.readline() 即可。
2. 对于文件的传输,用 FileInputStream /FileOutputStream 及 DataInputStream /DataOutputStream 及 os.write(), is.read() 即可。
3. 对于对象的传输,用 ObjectInputStream /ObjectOutputStream 及 os.writeObject(), is.readObject() 即可 .
public class FileSender { private ServerSocket ss = null; public FileSender() { } public void startSend(String filePath, int port) { // socket输出流 DataOutputStream os = null; // 文件输入流 DataInputStream is = null; // 建立socket连接 Socket socket = null; try { // 选择进行传输的文件 File file = new File(filePath); // 建立socket监听 ss = new ServerSocket(port); socket = ss.accept(); os = new DataOutputStream(socket.getOutputStream()); // 将文件名及长度传给客户端。这里要真正适用所有平台,例如中文名的处理,还需要加工, // 具体可以参见Think In Java 4th里有现成的代码。 os.writeUTF(file.getName()); os.flush(); os.writeLong((long) file.length()); os.flush(); is = new DataInputStream(new BufferedInputStream( new FileInputStream(filePath))); // 缓冲区大小 int bufferSize = 8192; // 缓冲区 byte[] buf = new byte[bufferSize]; // 传输文件 while (true) { int read = 0; if (is != null) { read = is.read(buf); } if (read == -1) { break; } os.write(buf, 0, read); } os.flush(); } catch (IOException e) { e.printStackTrace(); } finally { // 关闭所有连接 try { if (os != null) os.close(); } catch (IOException e) { } try { if (is != null) is.close(); } catch (IOException e) { } try { if (socket != null) socket.close(); } catch (IOException e) { } try { if (ss != null) ss.close(); } catch (IOException e) { } } } public static void main(String[] args) { new FileSender().startSend("E:\\JDK_API_1_6_zh_CN.CHM", 8821); } } import java.io.BufferedInputStream; import java.io.BufferedOutputStream; import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.FileOutputStream; import java.io.IOException; import java.net.Socket; import java.net.UnknownHostException; public class FileIncepter { public FileIncepter() { } public void getFile(String savePath, String ip, int port) { // 建立socket连接 Socket socket = null; try { socket = new Socket(ip, port); } catch (UnknownHostException e1) { e1.printStackTrace(); } catch (IOException e1) { e1.printStackTrace(); } // 建立socket输入流 DataInputStream inputStream = null; try { inputStream = new DataInputStream(new BufferedInputStream(socket .getInputStream())); } catch (IOException e1) { e1.printStackTrace(); } try { // 缓冲区大小 int bufferSize = 8192; // 缓冲区 byte[] buf = new byte[bufferSize]; int passedlen = 0; long len = 0; // 获取文件名称 savePath += inputStream.readUTF(); DataOutputStream fileOut = new DataOutputStream( new BufferedOutputStream(new BufferedOutputStream( new FileOutputStream(savePath)))); // 获取文件长度 len = inputStream.readLong(); System.out.println("文件的长度为:" + len + " KB"); System.out.println("开始接收文件!"); // 获取文件 while (true) { int read = 0; if (inputStream != null) { read = inputStream.read(buf); } passedlen += read; if (read == -1) { break; } System.out.println("文件接收了" + (passedlen * 100 / len) + "%"); fileOut.write(buf, 0, read); } System.out.println("接收完成,文件存为" + savePath); fileOut.close(); } catch (Exception e) { e.printStackTrace(); return; } } public static void main(String[] args) { new FileIncepter().getFile("F:\\", "localhost", 8821); } }转载自http://shenzhenchufa.blog.51cto.com/730213/280436
发表评论
-
输入一组数字,以逗号分隔,然后可选择升或者降序对其排序
2010-04-20 22:54 4592这是一道笔试题,在网上也看到一些人解答的,总感觉不好,今天我就 ... -
找出一个字符串中第一个无重复字符
2010-04-15 22:47 2151/** * 编写一个高效率函数来找出一个字符串中第一个无重 ... -
将一个字符穿Sting="1_2_3_4_5_6_7_8_9", 转变成String[]={"123","456","789"}.
2010-04-03 18:34 1779这是一道面试题,题目要求如下 要求不能使用split()方法, ... -
给一个任意字符组成的字符串统计每个字符出现的次数
2010-04-03 16:52 3283/** * 给一个任意字符组成的字符串统计每个字符出现的 ... -
java面试题(收藏)
2010-03-29 23:02 637http://blog.csdn.net/david2008m ... -
项目经验不多时如何在简历中包装自己?
2010-03-21 17:52 2189题目来自于论坛一个讨论中的话题 如何在简历中包装自己?比如没有 ... -
在面试时遇到不了解的问题,如何顺畅的与面试人员交流?(转载)
2010-03-21 17:51 1242比如突然问到的正好是 ... -
面试题转载
2010-03-15 23:43 1166Struts,Hibernate,Spring经典面试题收藏 ...
相关推荐
### Java多线程+Socket实现的漂亮QQ #### 技术要点分析 ##### 1. Java Swing Java Swing 是一个用于构建图形用户界面 (GUI) 的轻量级组件集,它为开发人员提供了丰富的功能来设计复杂的用户界面。在本项目中,...
在Python编程领域,构建一个基于`tkinter`的图形用户界面(GUI)应用程序,并结合多线程和`socket`网络编程技术,可以实现一个功能完善的网络登录和群聊聊天室。下面将详细介绍这些知识点。 首先,`tkinter`是...
在Linux操作系统中,多线程编程与网络通信的结合是一个重要的技术领域,特别是在服务器开发中。...对于初学者来说,这是一个很好的起点,通过动手实践,逐步掌握Linux多线程Socket编程的核心技巧。
标题"Netty技术文档,Socket技术,多线程"指出我们要讨论的是Netty框架,它与Socket编程以及多线程技术的结合。Netty是一个高性能、异步事件驱动的网络应用程序框架,用于快速开发可维护的高性能协议服务器和客户端...
总之,基于WCF的多线程SOCKET文件传输服务是一个复杂而实用的系统,它结合了WCF的易用性和SOCKET的灵活性,通过多线程实现了高效的文件并发传输。在设计和实现过程中,需要注意服务的可扩展性、安全性以及性能优化,...
在主线程中通过控制台读取键盘...服务器在收到一个socket连接之后,把该socket保存到队列中,并对队列中的每个socket开启各自的读写线程。测试可以在不同控制台运行server和client,服务器接收消息时,会显示消息来源
"多线程socket文件传输"是一个常见的应用场景,特别是在大数据交换、文件共享等需求中。本项目使用C语言实现了一个非阻塞的多线程socket文件传输程序,尽管可能存在一些问题,但对初学者来说,它能提供宝贵的实践...
Java Socket多线程文件传输实例项目是一个典型的网络编程应用场景,主要涉及了Socket编程、多线程处理以及文件I/O操作等关键知识点。在这个项目中,开发者利用Java的Socket API实现了一个能够支持多个客户端同时进行...
在本文中,我们将深入探讨如何使用Visual Studio 2017和C++来实现TCP套接字的多线程通信。TCP(传输控制协议)是一种面向连接、可靠的、基于字节流的通信协议,广泛应用于互联网上的各种服务。多线程技术则允许我们...
在本项目"基于Java+socket实现多线程聊天室-控制台版"中,开发者创建了一个简单的、基于命令行界面的多人聊天应用。这个应用利用了Java编程语言以及Socket网络编程技术来实现实时的通信功能。以下是关于这个项目的...
在多线程Socket文件传输中,通常会创建一个主线程负责管理连接和调度,而其他线程则分别处理文件的读写。这种方式允许并发处理多个文件传输,提高了系统的并行处理能力。对于断点续传功能,需要在客户端和服务器之间...
本文将深入探讨C#语言中使用Socket进行多线程多管道可断点传送大文件的技术细节。Socket是网络通信的基础,它提供了进程间的通信能力,使得数据可以在不同机器间传输。 首先,我们来理解"多线程"的概念。在C#中,多...
本文将深入探讨"异步和多线程socket通讯"这一主题,基于提供的描述和标签,我们将讨论如何利用多线程和异步机制来提升socket通信的效率和响应性。 首先,Socket是一种在应用程序与网络服务之间建立连接的接口,它...
### Delphi多线程Socket编程介绍 随着分布式系统的广泛应用,多任务并发技术变得越来越重要。在当前基于多线程的操作系统环境下,开发并发多任务程序已成为软件开发领域的一个热点话题。Delphi作为一种强大的开发...
在Java编程领域,多线程Socket通信是一种常见且重要的网络编程技术。Socket是TCP/IP协议栈中的一个关键组件,用于在网络中实现进程间的通信。在这个名为"JAVA写的多线程socket通信程序源码"的项目中,我们可以看到...
【C# Socket 多线程编程】在C#中,Socket编程是实现网络通信的关键,特别是在多线程环境中,能够高效地处理并发连接和数据传输。Socket是TCP/IP协议的基础,它代表了通信的两端点,允许不同主机或同一主机内的进程...
本项目“python聊天室---pyqt5+socket+Thread聊天室”旨在教授如何利用Python的PyQt5库创建一个聊天室应用,并通过Socket进行网络通信,同时采用多线程(Thread)来实现后台任务的异步执行。以下将详细解析这个项目的...
这个程序可能包含了上述步骤的代码实现,通过分析和学习这个示例,开发者可以更好地理解和掌握多线程Socket编程。 总的来说,使用Socket和多线程技术,我们可以构建出能够高效处理多个客户端请求的服务器。这种模型...
《VC_Socket_多线程文件传输》是一个基于C++实现的项目,它演示了如何在Windows环境下使用Visual Studio 2005进行多线程的文件上传与下载功能。这个项目的核心技术主要包括Socket编程、多线程处理以及文件操作,这些...
9. **代码示例**:多线程通信的代码通常包含Socket的创建、绑定、监听、连接、读写以及线程的创建和管理。具体实现可以参考提供的“多线程通信完成品”文件。 总的来说,基于TCP/IP的Socket多线程通信是实现高并发...